这个问题是关于在 PCRE 模式中使用前瞻、嵌套引用和条件来匹配所有回文的教育演示,包括那些不能被 PCRE 手册页中给出的递归模式匹配的回文。
在 PHP 片段中检查这个 PCRE 模式:
$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|.))$
手册页警告说这种递归模式不能检测所有回文(参见:Why will this recursive regex only match when a character repeats 2 n - 1 times? and also on ideone.com),但嵌套的参考/正向前瞻模式呈现在这个问题上可以。