Динамические регулярные выражения
Вместо этого могу показать технический прием, как можно завершить все регулярное выражение при выполнении какого-то условия. Например, в нашем случае нужно завершить поиск, если найдена последовательность цифр длиной четыре цифры. В начало всего регулярного выражения надо вставить условную конструкцию
(?(?{$len == 4})\G(?!))
При достижении этого условия встроенный код Perl вернет истину, и на место всей условной конструкции будет подставлен подшаблон
\G(?!)
Он говорит, что с конца предыдущего совпадения (или с начала текста при первой итерации поиска) нет совпадения. На этом все регулярное выражение закончит работу, т.к. итерация его со следующей позиции невозможна из-за привязки к концу предыдущего совпадения. В том месте, где вы установили, что надо поскорее выйти из регулярного выражения, подставьте подшаблон (?!), чтобы произошла итерация всего регулярного выражения. Но помните, что она не произойдет до тех пор, пока слева от текущей позици в шаблоне имеются квантификаторы или конструкции выбора альтернативы с сохраненными состояниями.
Что будет, если убрать атомарную группировку?
/((\d) (?{$d=$+}) (??{ ++$d < 10 ? "$d" : "(?!)" })* ) (?{print "$1\n"}) (?{ # Эти символы нельзя разделять if (length $1 > $len) { $len=length $1; $res=$1; } }) # Эту скобку нельзя отделять от предыдущей скобки "}" (?!) /x; print $res if defined $res;
Тогда на печать выйдет гораздо больше строк:
0123 012 01 0 123 12 1 23 2 3 1234 123 12 1 234 23 2 34 3 4 3456789 345678 34567 3456 345 34 3 456789 45678 4567 456 45 4 56789 5678 567 56 5 6789 678 67 6 789 78 7 89 8 9 1 0 3456789
Из этой распечатки видно, что после выполнения второго подшаблона (?!) не происходит итерация всего регулярного выражения, как в первом случае, ведь квантификатор * имеет сохраненные состояния. Он начинает отдавать по одной захваченной цифре, пока не отдаст их все. Только после этого происходит рестарт всего регулярного выражения со следующего символа целевого текста.