Wie erkennt dieses PCRE-Muster Palindrome?
Diese Frage ist eine didaktische Demonstration der Verwendung von Lookahead, verschachtelten Verweisen und Bedingungen in einem PCRE-Muster, um ALLE Palindrome abzugleichen, einschließlich derer, die nicht mit dem in der PCRE-Manpage angegebenen rekursiven Muster übereinstimmen.
Prüfen Sie dieses PCRE-Muster im PHP-Snippet:
$palindrome = '/(?x)
^
(?:
(.) (?=
.*
(
\1
(?(2) \2 | )
)
$
)
)*
.?
\2?
$
/';
Dieses Muster scheint Palindrome zu erkennen, wie in diesen Testfällen siehe auch auf 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);
}
Wie funktioniert dieses Muster?
AnmerkungeDieses Muster verwendet einnested reference, eine ähnliche Technik wieWie erkennt dieser Java-Regex Palindrome?, aber im Gegensatz zu diesem Java-Muster gibt es kein Lookbehind (aber es verwendet einbeding).
eachten Sie auch, dass der PCREman page präsentiert ein rekursives Muster, das mit einigen Palindromen übereinstimmt:
# the recursive pattern to detect some palindromes from PCRE man page
^(?:((.)(?1)\2|)|((.)(?3)\4|.))$
Die Manpage warnt, dass dieses rekursive Muster NICHT alle Palindrome erkennen kann (siehe:Warum stimmt diese rekursive Regex nur dann überein, wenn ein Charakter 2 @ wiederhon - 1 mal undauch auf ideone.com), aber das in dieser Frage dargestellte verschachtelte Referenz- / Positiv-Lookahead-Muster kann.