Рекурсивное PHP Regex

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

Этот вопрос касается разъяснения поведения механизма регулярных выражений php для рекурсивных выражений. (Если у вас есть идеи о том, как правильно сопоставить приведенные ниже строки без использования рекурсивного регулярного выражения php, это очень круто, но вопрос не в этом.)

a(?:(?R)|a?)a

Это простое выражение, целью которого является сопоставление символа «а» или ничего, вложенного в одно или несколько гнезд символа «а». Например, аа, ааа, аааа, ааааа. Для этого не нужно использовать рекурсию:

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 : no match
aa : aa
aaa : aaa
aaaa : aaa
aaaaa : aaaaa
aaaaaa : aaa

Может кто-нибудь объяснить, что происходит на третьей и пятой строках вывода? Я попытался проследить путь, который, как мне кажется, должен идти двигатель, но, должно быть, я представлял его неправильно. Почему движок возвращает "aaa" вместо "aaaa"? Что делает его таким нетерпеливым? Я, должно быть, представляю совпадающее дерево в неправильном порядке.

Я понимаю, что

#(?:a|a(?R)a)*#

вроде работает, но мой вопрос в том, почему другой шаблон не работает.

Большое спасибо!

25
задан zx81 10 December 2011 в 20:57
поделиться