Этот вопрос является образовательной демонстрацией использования lookahead, вложенной ссылки и условных выражений в шаблоне 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 нет lookbehind (но он использует conditional).
Кроме того, обратите внимание, что страница PCRE представляет собой рекурсивный шаблон для соответствия некоторым палиндромам:
# the recursive pattern to detect some palindromes from PCRE man page
^(?:((.)(?1)\2|)|((.)(?3)\4|.))$
Страница man предупреждает, что этот рекурсивный шаблон НЕ может обнаружить все палиндромы (см. Почему это рекурсивное регулярное выражение будет соответствовать только тогда, когда символ повторяет 2 n - 1 раз? и также на ideone.com), но вложенный шаблон/позитивный шаблон обзора, представленный в этом вопросе, может.