0

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

foo:bar //Does not match

foo\:bar //Does match

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

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

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

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

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

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

表达式匹配。

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

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

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

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

4

2 回答 2

1

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

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

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

于 2013-10-17T11:10:40.863 回答
1

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

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

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

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

这匹配一个非冒号[^:],或者它匹配\\[:]一个文字,然后[是一个文字:,然后是一个文字]

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

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

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

这就是发生[^:]的情况:匹配f然后它匹配o然后另一个o然后它匹配它E,现在它找到一个冒号:并且它无法匹配它,但是由于默认情况下PCRE引擎不会寻找最长可能的匹配它是满意的到目前为止匹配的内容并停在那里并fooE作为匹配返回,而根本不尝试其他替代方案E[:] (顺便说一句,它等于E:

如果您想匹配整个序列,那么您将使用如下表达式:

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

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

于 2013-10-17T11:14:05.000 回答