Фигурные скобки с {} grep и регулярными выражениями: почему оно превышает максимальное значение?

Я уже некоторое время самостоятельно изучаю сценарии оболочки и наткнулся на этот раздел руководства по основам Linux, касающийся grep и фигурных скобок {}. Моя проблема в том, что когда я запрашиваю шаблон строки для поиска с использованием grep от минимального до максимального количества вхождений с использованием {} или фигурных скобок, мой результат превышает указанный мной максимум.

Вот что произошло:

Express11:~/unix_training/reg_ex # cat reg_file2
ll
lol
lool
loool
loooose
Express11:~/unix_training/reg_ex # grep -E 'o{2,3}' reg_file2
lool
loool
loooose
Express11:~/unix_training/reg_ex #

Когда, согласно руководству, этого не должно быть, поскольку я указываю здесь, что я ищу только строки, содержащие от двух последовательных o до трех последовательных o.

РЕДАКТИРОВАТЬ: На самом деле, причина, по которой я не понял, как работают фигурные скобки, заключалась в этом упрощенном объяснении в руководстве. И цитирую:

19.4.10. между n и m раз И здесь мы требуем ровно от минимума 2 до максимума 3 раза.

paul@debian7:~$ cat list2
ll
lol
lool
loool
paul@debian7:~$ grep -E 'o{2,3}' list2
lool
loool
paul@debian7:~$ grep 'o\{2,3\}' list2
lool
loool
paul@debian7:~$ cat list2 | sed 's/o\{2,3\}/A/'
ll
lol
lAl
lAl
paul@debian7:~$

Спасибо всем, кто ответил.


person user3873164    schedule 11.02.2015    source источник
comment
Самое замечательное в Google то, что он позволяет вам взять описание, подобное этому упрощенному объяснению в руководстве, и узнать, о каком руководстве идет речь. На самом деле это вовсе не руководство; это книга под названием «Основы Linux» Пола Коббо, вводный текст для начинающих администраторов, которая вообще не посвящена регулярным выражениям. Существует справочная страница по регулярным выражениям (вероятно, в вашей системе: попробуйте man 7 regex), и в Интернете есть множество ресурсов по регулярным выражениям. Некоторые из них даже не так уж плохи.   -  person rici    schedule 11.02.2015
comment
В этом особом случае вы можете понять, что вам нужны 2, а не 4 последовательных o. Таким образом, вы можете использовать: grep oo reg_file2 | grep -v oooo.   -  person gniourf_gniourf    schedule 11.02.2015


Ответы (2)


# grep -E 'o{2,3}' reg_file2
lool
loool
loooose

Команда работает отлично, так как соответствует первым трем o в последней строке. Вот почему вы также получаете последнюю строку в окончательном выводе.

Я думаю, что команда, которую вы на самом деле ищете,

$ grep -P '(?<!o)o{2,3}(?!o)' file
lool
loool

Пояснение:

  • (?<!o) отрицательный просмотр назад, который утверждает, что совпадению не будет предшествовать буква o.

  • o{2,3} Соответствует 2 или 3 o.

  • (?!o) Отрицательный просмотр вперед, утверждающий, что за совпадением не будет следовать буква o.

ИЛИ

$ grep -E '(^|[^o])o{2,3}($|[^o])' file
lool
loool

Пояснение:

  • (^|[^o]) Соответствует началу строки ^ или любому символу, но не o

  • o{2,3} Соответствует 2 или 3 o

  • ($|[^o]) Соответствует концу строки $ или любому символу, кроме o

person Avinash Raj    schedule 11.02.2015
comment
Спасибо за скромный ответ. - person user3873164; 11.02.2015

Вы не понимаете, как работает регулярное выражение.

Шаблон o{2,3} в grep будет проходить через каждую строку в поисках oo и ooo. Пока есть совпадение, Grep предоставит вам эту строку. Поскольку вы не добавляли другие правила в свой шаблон, то, что вы получаете от grep -E 'o{2,3}' reg_file2, верно.

Я предполагаю, что в вашем случае вам нужны только две или три последовательные буквы «о». Таким образом, вам нужно будет использовать регулярное выражение, подобное тому, что ответил Радж. Соответствие oo или ooo, за которыми не следует ни буква "о", ни после нее.

person Lution    schedule 11.02.2015
comment
Спасибо за быстрый ответ. Я отредактировал свой вопрос и начал использовать регулярные выражения всего неделю на основе базового руководства. - person user3873164; 11.02.2015