Подтвердить что ты не робот

ERE - добавление квантификатора для группировки с внутренней группой и обратной ссылкой

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

$ grep --version | head -n1
grep (GNU grep) 2.25

$ # consecutive repeated letters occurring twice
$ grep -m5 -xiE '[a-z]*([a-z])\1[a-z]*[a-z]*([a-z])\2[a-z]*' /usr/share/dict/words
Abbott
Annabelle
Annette
Appaloosa
Appleseed

$ # no output for this, why?
$ grep -m5 -xiE '([a-z]*([a-z])\2[a-z]*){2}' /usr/share/dict/words


Работает с -P хотя

$ grep -m5 -xiP '([a-z]*([a-z])\2[a-z]*){2}' /usr/share/dict/words
Abbott
Annabelle
Annette
Appaloosa
Appleseed

$ grep -m5 -xiP '([a-z]*([a-z])\2[a-z]*){3}' /usr/share/dict/words
Chattahoochee
McConnell
Mississippi
Mississippian
Mississippians


Спасибо Casimir et Hippolyte за то, что вы предложили более простой ввод и регулярное выражение, чтобы проверить это поведение.

$ echo 'aazbb' | grep -E '(([a-z])\2[a-z]*){2}' || echo 'No match'
aazbb
$ echo 'aazbbycc' | grep -E '(([a-z])\2[a-z]*){2}([a-z])\3[a-z]*' || echo 'No match'
aazbbycc
$ echo 'aazbbycc' | grep -P '(([a-z])\2[a-z]*){3}' || echo 'No match'
aazbbycc

$ # failing case
$ echo 'aazbbycc' | grep -E '(([a-z])\2[a-z]*){3}' || echo 'No match'
No match

То же поведение, наблюдаемое при sed, а также

$ sed --version | head -n1
sed (GNU sed) 4.2.2

$ echo 'aazbb' | sed -E '/(([a-z])\2[a-z]*){2}/! s/.*/No match/'
aazbb    
$ echo 'aazbbycc' | sed -E '/(([a-z])\2[a-z]*){2}([a-z])\3[a-z]*/! s/.*/No match/'
aazbbycc

$ # failing case
$ echo 'aazbbycc' | sed -E '/(([a-z])\2[a-z]*){3}/! s/.*/No match/'
No match


Связанные ссылки поиска, я проверил некоторые из них, но не получил ничего близкого к этому вопросу

Если это разрешено в более новой версии grep или sed, дайте мне знать. Кроме того, если проблема наблюдается в реализациях, отличных от GNU

4b9b3361

Ответ 1

Я полагаю, что -E не позволяет Quantifiers, поэтому он работает только с -P


для сопоставления двух или более последовательных групп повторяющихся букв:

grep -P '(?:([a-z])\1*([a-z])\2){1}' /usr/share/dict/words

чтобы соответствовать 3 или более последовательным группам повторяющихся букв:

grep -P '(?:([a-z])\1*([a-z])\2){2}' /usr/share/dict/words

Параметры:

-P, --perl-regexp         PATTERN is a Perl regular expression

Ответ 2

Обновить

После поиска, я установил gnugrep32 в окно окна, затем запустил некоторые тесты:

Я прочитал это со старого сообщения SO:

Нежелательное соответствие не является частью синтаксиса Extended Regular Expression, поддерживаемого grep

Итак, мы используем [a-z]{0,20} как тест вместо [a-z]* или [a-z]*?, где ? игнорируется (wtf?)

Ниже приведены инкрементные тесты, использующие overal (){n}, чтобы увидеть, как далеко он пройдет, прежде чем он остановится. BACKTRACKING
в рамки.


Мин для работы

(([a-z])\2[a-z]{0,20}){1}   len = 2    rr
(([a-z])\2[a-z]{0,20}){2}   len = 4    rrrr
(([a-z])\2[a-z]{0,20}){3}   len = 25   rrrrrrrrrrrrrrrrrrrrrrrrr
(([a-z])\2[a-z]{0,20}){4}   len = 47   rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
(([a-z])\2[a-z]{0,20}){5}   len = 69   rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
(([a-z])\2[a-z]{0,20}){6}   len = 91   rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr

От {3} до {6} длина дельты равна 22.

Это будет полная длина выражения кадра захвата ([a-z])\2[a-z]{0,20}
когда он не возвращается в предыдущие кадры.

Заключение заключается в том, что он автоматически останавливает откат после 2 кадров.

Это приводит к тому, что, например, из 20 кадров он достигает 16 и находит, что он не может совпадать.
Shoud, вернитесь к кадру 1 и настройте там и попробуйте все это на agaqin.

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

Конечно, нет теста для (([a-z])\2[a-z]*){3}, так как жадный квантор *
будет потреблять всю строку на втором кадре, если они все [a-z] и даже не запустите третий кадр.

Ответ 3

$ # no output for this, why?
$ grep -m5 -xiE '([a-z]*([a-z])\2[a-z]*){2}' /usr/share/dict/words

Потому что вы ищете двойную группу (дважды то же), у которой есть (по крайней мере) двойная буква внутри. Что-то вроде abbcabbc [(...) = "abbc" 2 раза], а не 2 (в конечном итоге аналогичная) группа, каждая из которых имеет двойную букву внутри, как abbcdeef.

с 2 back ref:

$ grep -iE '[a-z]*([a-z])\1{1,}[a-z]*([a-z])\2{1,}[a-z]*`