Почему Perl ленив, когда регулярное выражение совпадает с * в группе?
В perl *
обычно жадный, если вы не добавите ?
после него. Однако, когда *
используется против группы, ситуация кажется иной. Мой вопрос "почему". Рассмотрим этот пример:
my $text = 'f fjfj ff';
my (@matches) = $text =~ m/((?:fj)*)/;
print "@matches\n";
# --> ""
@matches = $text =~ m/((?:fj)+)/;
print "@matches\n";
# --> "fjfj"
В первом матче перл лениво ничего не выводит, хотя он мог бы что-то сопоставить, как показано во втором матче. Как ни странно, поведение *
является жадным, как ожидалось, когда содержимое группы просто .
вместо фактических символов:
@matches = $text =~ m/((?:..)*)/;
print "@matches\n";
# --> 'f fjfj f'
- Примечание. Вышеописанное было проверено на perl 5.12.
- Примечание. Неважно, использую ли я захватывающие или не захватывающие круглые скобки для внутренней группы.
Ответы
Ответ 1
Это не вопрос жадного или ленивого повторения. (?:fj)*
жадно сопоставляет столько повторений "fj", сколько может, но он будет успешно соответствовать нулевым повторениям. Когда вы попытаетесь сопоставить его со строкой "f fjfj ff"
, она сначала попытается совпадения в позиции нуля (до первого "f" ). Максимальное количество раз, когда вы можете успешно сопоставить "fj" в нуле нулевой позиции, равно нулю, поэтому шаблон успешно соответствует пустой строке. Поскольку шаблон успешно сопоставлен с нулевым положением, мы закончили, и у двигателя нет причин попробовать совпадение в более поздней позиции.
Мораль этой истории: не пишите шаблон, который не может ничего сопоставить, если вы не хотите, чтобы он ничего не соответствовал.
Ответ 2
Perl будет соответствовать как можно раньше в строке (самый левый). Он может сделать это с вашим первым совпадением, сопоставляя нулевые вхождения fj
в начале строки