Я экспериментирую с функциями регулярных выражений named subpattern / 'subroutine' в PHP PCRE, и я надеюсь, что кто-то сможет объяснить следующий странный вывод:
$re = "/ (?(DEFINE) (?<a> a ) ) ^(?&a)$ /x"; var_dump(preg_match($re, 'a', $match)); // (int) 1 as expected var_dump($match); // Array( [0] => 'a' ) <-- Why?
Я не понимаю, почему названная группа «a» не находится в результате (с содержимым «a»). Изменение preg_match
до preg_match_all
помещает «a» и «1» в данные сопоставления, но оба содержат только пустую строку.
Мне очень нравится идея писать регулярные выражения таким образом, так как вы можете сделать их невероятно мощными, сохраняя их очень удобными (см. Этот ответ для хорошего примера), однако, если подшаблоны недоступны в данных сопоставления, тогда это не много использование действительно.
Я что-то упустил здесь или должен ли я оплакивать то, что могло бы быть, и двигаться дальше?
Совершенно очевидно, что эти подшаблоны не будут захватывать группу – их основная цель – использовать ее более одного раза, так что вы не сможете их полностью захватить. Кроме того, если по умолчанию было зафиксировано все подшаблоны, это не даст вам возможности не записывать группу, в которой вы ее не хотите, а не по умолчанию. Противоположность тривиальна – вы можете захватить, добавив еще одну группу вокруг инструкции (?&a)
A (?&a)
.
Я не мог найти ссылку на это на PCRE.org . Самое близкое это, что актуально, потому что вы не согласны (?<a>...)
напрямую (хотя вы можете ожидать пустую группу):
Любые скобки для записи, которые установлены во время вызова подпрограммы, возвращаются к их предыдущим значениям позже.
В руководстве Perl более четко указано (выделена соответствующая часть):
Пример того, как это можно использовать, выглядит следующим образом:
/(?<NAME>(?&NAME_PAT))(?<ADDR>(?&ADDRESS_PAT)) (?(DEFINE) (?<NAME_PAT>....) (?<ADRESS_PAT>....) )/x
Обратите внимание, что буферы захвата, согласованные внутри рекурсии, недоступны после возвращения рекурсии , поэтому необходим дополнительный уровень захватных буферов.