grep grouping with wildcards печатает весь файл без сопоставления

Группирование с помощью grep с использованием круглых скобок и объединение этого с подстановочным знаком, например * или ? , распечатает весь файл, но не выделяет совпадений, которые должны были быть найдены.

Пример test.txt :

find this
asdffind this
find this asdf
sadffind thisasdf
(find this)
(find this)?

grep -in "найти это" test.txt :
найти это
asdf найти это
найти это asdf
sadf найдите это asdf
( найдите это )
( найти это )?

grep -in "\ (найти это \)" тест.txt :
найдите это
asdf найдите это
найдите это asdf
sadf найдите этот asdf
( найдите это )
( найти это )?

grep -in "\ (найти это \) \?" test.txt :
найти это
найти это <- почему не нашел это сопоставленным?
asdffind this <- почему не нашел, что это сопоставлено?
найти это asdf
sadffind thisasdf <- почему не нашел, что это соответствует?
(найдите это) <- почему не нашел, что это соответствует?
(найти это)? <- почему не нашел совпадения с этим ?

С помощью ? обнаруживаются только фразы, начинающиеся в начале строки. Это также верно для символа * .

Я пытаюсь применить подстановочный знак ? ко всей фразе . Без круглых скобок он будет применяться только к последнему слову, на котором оно находится, да?
grep "find this \?" применяет ? только к this , что это не то, что я хочу.

Редактировать:

Я думаю, что моя проблема в том, что я пытаюсь трактовать «словосочетание» как одно слово, что не работает.

-1
18.04.2017, 17:33
2 ответа

Я думаю, ваша проблема в том, что вы думали, что вам нужно избегать круглых скобок, чтобы отключить группировку, хотя на самом деле это позволяет их экранировать. Например, чтобы напечатать только те строки, которые соответствуют (найдите это) , вы должны выполнить:

$ grep -in "(find this)" test.txt
5:(find this)
6:(find this)?

Если вы выйдете из скобок ( \ (\) ), вы сообщите ] grep не обрабатывать ( и ) как обычные символы, а как специальные "групповые" разделители. Это, например, позволяет вам делать такие вещи, как:

$ echo "foofoo" | grep -o '\(.oo\)\1'
foofoo

Это соответствует любому символу, за которым следуют два символа Os ( .oo ), но поскольку он заключен в экранированные круглые скобки, теперь мы можем ссылаться на все, что было найдено, как \ 1 , что позволяет сопоставить foofoo с \ (. Oo \). * \ 1 .

То же самое и с ? . Если только он не следует за подстановочным знаком регулярного выражения, например . , это просто нормальный персонаж. Итак, чтобы сопоставить строку с (найти это)? , вы должны сделать:

$ grep -in "(find this)?" test.txt
6:(find this)?
1
28.01.2020, 05:08

Я не знаю, что вы на самом деле пытаетесь сделать (ваши объяснения не имеют смысла), поэтому я отвечу только, чтобы объяснить, что делают команды, которые вы опубликовали. Как было отмечено в комментариях, возможно, вы столкнулись с ошибкой в старой версии grep; попробуйте более свежую версию (например, на современном дистрибутиве Linux или из Homebrew).

Grep ищет строки, содержащие совпадение с заданным шаблоном. Выводом grep является вся строка, независимо от того, какая часть строки совпала. (Опция -o изменяет это.) Например, grep a test.txt выводит все строки, содержащие a. Все строки, а не только a.

В частности, если шаблон может соответствовать пустой строке, то grep выведет все строки. Например, поскольку \? является оператором нуля или единицы, grep 'a\?' test.txt выводит все строки, которые либо содержат a, либо содержат пустую строку. Так как все строки содержат пустую строку, то печатаются все строки.

Аналогично grep "\(find this\)\?" печатает все строки, которые либо содержат find this, либо пустую строку, поэтому печатает все строки. Оператор \? применяется к группе find this (обратные косые скобки разграничивают группу в синтаксисе regex по умолчанию для grep).

Выделение применяется поверх поведения по сопоставлению строк. Когда есть несколько вариантов соответствия строки, не уточняется, какую часть grep будет считать соответствующей, за исключением того, что в документации (по состоянию на GNU grep 2.25) говорится, что по возможности будет использоваться непустое соответствие. Я думаю, что GNU grep использует самое длинное совпадение.

Обратите внимание, что операторы никогда не применялись к "словам". Они применяются к предыдущему символу или группе в скобках. Например, найти это\? означает "либо найти это, либо найти ти" - оператор \? применяется только к последнему с. Чтобы подобрать find или find this, используйте группу: find\( this\)\?.

1
28.01.2020, 05:08

Теги

Похожие вопросы