字符类在正则表达式中的替换中的奇怪行为

时间:2013-10-17 11:07:23

标签: php regex

我正在尝试编写一个简单的正则表达式,它可以识别不是列或转义列的字符序列。 即:

foo:bar //Does not match

foo\:bar //Does match

根据我对常规语言的了解,这种语言可以用正则表达式来描述

/([^:]|\\[:])*/

您可以在精彩工具Regexper

中看到此表达式的图形表示

使用php的preg_match(基于PCRE引擎),这样的表达式与“foo \:bar”不匹配。

但是,如果用单个char替换该类:

/([^:]|\\:)*/

表达式匹配。

你对此有解释吗?这是对字符类的PCRE引擎的限制吗?

PS:在基于AS3 Regexp引擎的RegExr上测试第一个表达式,在改变交替顺序时不提供匹配:

/(\\[:]|[^:])*/

它匹配,而PCRE中的相同表达式不匹配。

2 个答案:

答案 0 :(得分:1)

你可以试试这个。这允许secuence \\:在否定的角色类[^:]之前有机会。

^(?:\\:|[^:])+$

如果您使用交替栏中的值,如^((?:[^:]|\\:)+$中那样,它将与转义冒号\:不匹配,因为第一个选项将在第二个表达式之前使用斜杠(\)有机会尝试。

答案 1 :(得分:1)

preg_match()接受正则表达式模式作为字符串,因此您需要双重转义所有内容。

^(?:[^:\\\\]|\\\\:)+$

匹配一个或多个非冒号或转义字符[^:\\\\]或转义冒号\\\\:的字符。

为什么你的第一个正则表达式不起作用:/([^:]|\\[:])*/

这匹配非冒号[^:],或者匹配\\[:],其匹配文字[,后跟文字:,然后是文字]

为什么会这样:/([^:]|\\:)*/

这与非冒号[^:]匹配,或者与文字\\:匹配,因此它可以有效地匹配所有内容。

修改:为什么/([^:]|E[:])*/fooE:bar不匹配?

会发生这种情况:[^:]f匹配,然后匹配o,然后匹配o,然后匹配E,现在它找到了冒号:并且它不匹配,但是因为默认情况下PCRE引擎不会查找最长匹配,它对目前已匹配的内容感到满意并且在那里停止并返回{{1}在没有尝试其他替代fooE 的情况下(完全相同于E[:]

如果你想匹配整个序列,那么你将使用像这样的表达式:

E:

这可以防止/([^:E]|E[:])*/ 使用[^:]