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


Character classes strange behavior in alternations in regular expressions

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

foo:bar //Does not match

foo':bar //Does match
根据我对正则语言

的了解,这种语言可以用正则表达式来描述

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

您可以在精彩的工具Regexper中看到此表达式的图形表示

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

但是,如果用单个字符替换类:

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

表达式匹配。

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

PS:在正则表达式上测试第一个表达式,即基于 AS3 正则表达式引擎,在更改交替顺序时不提供匹配:

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

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

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

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

这将匹配一个或多个不是冒号或转义字符的字符[^:''''],或者转义冒号'''':

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

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

为什么这样做:/([^:]|'':)*/

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

编辑:为什么/([^:]|E[:])*/不匹配fooE:bar

发生这种情况:[^:]匹配f然后匹配o然后匹配另一个o然后匹配E,现在它找到一个冒号:并且无法匹配它,但由于默认情况下 PCRE 引擎不寻找最长的可能匹配,它对到目前为止匹配的内容感到满意并停在那里并返回fooE作为匹配而不尝试另一种选择E[:](顺便说一下,它等于E:)。

如果要匹配整个序列,则将使用如下所示的表达式:

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

这可以防止[^:]消耗该E

你可以

试试这个。这允许安全'':有机会在否定字符类[^:]之前。

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

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