EDIT: я выбрал ответ ridgerunner, поскольку в нем содержится информация, необходимая для решения проблемы. Но мне также хотелось добавить полностью определенное решение к конкретному вопросу, если кто-то еще захочет полностью понять пример. Вы найдете его где-то внизу.
Этот вопрос касается уточнения поведения php regex engine для рекурсивных выражений. (Если вы думаете, как правильно соответствовать строкам ниже, не используя рекурсивное регулярное выражение php, это очень круто, но это не вопрос.)
a(?:(?R)|a?)a
Это простое выражение, которое нацелено на совпадение символа "a" или ничего, вложенного в одно или несколько гнезд символа "a" . Например, aa, aaa, aaaa, aaaaa. Для этого вам не нужно использовать рекурсию:
aa*a
будет работать отлично. Но нужно использовать рекурсию.
Вот фрагмент кода, который вы можете запустить, чтобы проверить мой неудачный шаблон:
<?php
$tries=array('a','aa','aaa','aaaa','aaaaa','aaaaaa');
$regex='#a(?:(?R)|a?)a#';
foreach ($tries as $try) {
echo $try." : ";
if (preg_match($regex,$try,$hit)) echo $hit[0]."<br />";
else echo 'no match<br />';
}
?>
В шаблоне два символа "a" формируют чередование. В чередовании мы либо сопоставляем рекурсию всего шаблона (два "a" с кадрированием чередования), либо символ "a" , необязательно пустые.
На мой взгляд, для "aaaa" это должно соответствовать "aaaa" .
Но вот вывод:
a : no match
aa : aa
aaa : aaa
aaaa : aaa
aaaaa : aaaaa
aaaaaa : aaa
Может кто-нибудь объяснить, что происходит на третьей и пятой строках вывода? Я попытался проследить путь, который, как я полагаю, должен принимать двигатель, но я должен вообразить это неправильно. Почему двигатель возвращает "aaa" в соответствие с "aaaa" ? Что заставляет его так стремиться? Я должен вообразить совпадающее дерево в неправильном порядке.
Я понимаю, что
#(?:a|a(?R)a)*#
вид работ, но мой вопрос в том, почему другой шаблон не делает.
Спасибо, кучи!