Как этот PCRE паттерн обнаруживает палиндромы?
Этот вопрос является образовательной демонстрацией использования предпросмотра, вложенных ссылок и условных выражений в шаблоне PCRE для соответствия ВСЕМ палиндромам, включая те, которые не могут быть сопоставлены с рекурсивным шаблоном, приведенным на справочной странице PCRE.
Изучите этот шаблон PCRE в фрагменте PHP:
$palindrome = '/(?x)
^
(?:
(.) (?=
.*
(
\1
(?(2) \2 | )
)
$
)
)*
.?
\2?
$
/';
Этот паттерн, кажется, обнаруживает палиндромы, как видно из этого теста (смотрите также на ideone.com):
$tests = array(
# palindromes
'',
'a',
'aa',
'aaa',
'aba',
'aaaa',
'abba',
'aaaaa',
'abcba',
'ababa',
# non-palindromes
'aab',
'abab',
'xyz',
);
foreach ($tests as $test) {
echo sprintf("%s '%s'\n", preg_match($palindrome, $test), $test);
}
Так как же работает этот шаблон?
ЗаметкиЭтот шаблон используетвложенная ссылка, который является аналогичным методом, используемым вКак это регулярное выражение Java обнаруживает палиндромы?, но в отличие от этого шаблона Java, нет никакого взгляда назад (но он используетусловный).
Также обратите внимание, что PCREсправочная страница представляет рекурсивный шаблон для соответствия некоторым палиндромам:
# the recursive pattern to detect some palindromes from PCRE man page
^(?:((.)(?1)\2|)|((.)(?3)\4|.))$
Страница man предупреждает, что этот рекурсивный шаблон НЕ может обнаружить все палиндромы (см .:Почему это рекурсивное регулярное выражение совпадает только тогда, когда персонаж повторяет 2n - 1 раз? а такжетакже на ideone.com), но вложенная справочная / позитивная прогнозная картина, представленная в этом вопросе, может.