这个问题是一个教育演示,展示了在PCRE模式中使用前瞻、嵌套引用和条件语句来匹配所有回文字符串的用法,包括那些不能被PCRE手册中递归模式匹配的字符串。请检查这个PHP片段中的PCRE模式:
这个 man 手册警告说,这个递归模式不能检测到所有的回文字符串(参见:为什么这个递归正则表达式只能在字符重复 2n - 1 次时匹配? 和 ideone.com 上的例子),但是这个问题中呈现的嵌套引用/正向先行断言模式可以。
$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);
}
那么这个模式是如何工作的呢?
注释
这个模式使用了 嵌套引用,这是一种类似于 How does this Java regex detect palindromes? 中使用的技术,但与该 Java 模式不同的是,它没有向后查找(但它确实使用了 条件语句)。
此外,请注意 PCRE man page 提供了一个递归模式来匹配一些回文:
# the recursive pattern to detect some palindromes from PCRE man page
^(?:((.)(?1)\2|)|((.)(?3)\4|.))$
这个 man 手册警告说,这个递归模式不能检测到所有的回文字符串(参见:为什么这个递归正则表达式只能在字符重复 2n - 1 次时匹配? 和 ideone.com 上的例子),但是这个问题中呈现的嵌套引用/正向先行断言模式可以。
java.util.regex.Pattern
,MSDN/.NET Framework 4/Regular Expression Language Elements,http://www.regular-expressions.info/。毫无疑问,还有更好的资源可用,但这几乎是我使用的全部资源。 - polygenelubricants