странное поведение grep с однобуквенными словами

10

Я удаляю стоп-слова из текста, примерно используя этот код

У меня есть следующее

$ cat file
file
types
extensions

$ cat stopwords
i
file
types

grep -vwFf stopwords file

Я ожидаю результата: extensions

но я получаю (я думаю, что неправильно)

file
extensions

Это как если бы слово fileбыло пропущено в файле стоп-слов. Теперь вот прохладно немного: если я изменить файл игнорируемых слов, путем изменения одного слова / буквы iна первой линии, в любой другой ASCii буквы , кроме f, i, l, e, то та же команда Grep дает мне другой и правильный результат extensions.

Что здесь происходит и как мне это исправить?

Я использую grep (BSD grep) 2.5.1-FreeBSD на bash Mac OSX GNU, версия 4.4.12 (1)

Тим
источник
Вы можете использовать -xпереключатель для регулярного выражения строки вместо -wслова? Тем не менее, я думаю, что -Fпереключатель отменит либо один из них, либо наоборот.
jesse_b
grep (GNU grep) 3.1 работает так, как вы ожидаете.
Хауке Лагинг
Я повторил это. Еще один факт: создание iшаблона вместо второго шаблона в stopwordsфайле также изменяет поведение.
JdeBP
Я не могу воспроизвести поведение на OpenBSD 6.2 с нативным grepили с GNU grep3.1.
Кусалананда

Ответы:

13

Это было ошибкой bsdgrep, связанной с переменной, которая отслеживает часть текущей строки, все еще сканируемой, которая перезаписывается последовательными вызовами механизма сопоставления регулярных выражений, когда задействованы несколько шаблонов.

местное исправление

Вы можете обойти это в некоторой степени, не используя -wопцию, которая полагается на эту переменную для правильной работы и, следовательно, терпит неудачу, а вместо этого используя расширения регулярных выражений, которые соответствуют началу и концу слов, делая ваш stopwordsфайл похожим на:

\ <Я \>
\ <Файл \>
\ <типы \>

Этот обходной путь также потребует, чтобы вы не использовали эту -Fопцию.

Обратите внимание, что документированные компоненты регулярных выражений [[:<:]]и [[:>:]]о которых re_formatвам расскажет руководство, работать здесь не будут . Это связано с тем, что в библиотеке регулярных выражений, в которую встроена библиотека bsdgrepGNU, включена поддержка совместимости регулярных выражений GNU. Это еще одна ошибка, которая, как сообщается, исправлена.

исправление

Эта ошибка была исправлена ​​ранее в этом году. Исправление еще не вошло в STABLE или RELEASE версий FreeBSD, но, по сообщениям, находится в CURRENT.

Чтобы получить это в версии для MacOS grep, которая является производной от FreeBSD bsdgrep, пожалуйста, обратитесь в Apple. ☺

дальнейшее чтение

JdeBP
источник
Хорошо, и спасибо за сообщение об этом. Я нашел бы этот ответ еще более захватывающим, если бы он цитировал ошибочный код.
Даг
1

Этот код:

pl " Input data file data1 and stopwords file data2:"
head data1 data2

pl " Expected output:"
cat $E

pl " Results, grep:"
# grep -vwFf stopwords file
grep -vwFf data2 data1

pl " Results, cgrep:"
cgrep -x1 -vFf data2 data1

производит:

-----
 Input data file data1 and stopwords file data2:
==> data1 <==
file
types
extensions

==> data2 <==
i
file
types

-----
 Expected output:
extensions

-----
 Results, grep:
file
extensions

-----
 Results, cgrep:
extensions

В такой системе, как:

OS, ker|rel, machine: Apple/BSD, Darwin 16.7.0, x86_64
Distribution        : macOS 10.12.6 (16G29), Sierra
bash GNU bash 3.2.57

Более подробная информация о cgrep, доступна через brew и sourceforge:

cgrep   shows context of matching patterns found in files (man)
Path    : ~/executable/cgrep
Version : 8.15
Type    : Mach-O64-bitexecutablex86_64 ...)
Home    : http://sourceforge.net/projects/cgrep/ (doc)

ура, дрл

DRL
источник
только что получил себе новый grep.
Тим
@Tim - Надеюсь, вы найдете cgrep таким же полезным, как и я. Скорость тестов, которые я провел, примерно соответствует уровню GNU grep, а функции «контекст / оконное управление» очень полезны. Он также легко собирается на системах Linux ... ура, drl
drl