1

当我尝试这个正则表达式时

\"(\S\S+)\"(?!;c)

在这个字符串上"MM:";d它符合我的要求

在这个字符串"MM:";c上,它与所期望的不匹配。

但是当我添加第二组时,通过在该组中移动分号并使用 | 使其成为可选

\"(\S\S+)\"(;|)(?!c)

对于这个字符串"MM:";c当我期望它不像以前那样匹配时。

我在 Java 上尝试了这个,然后在 Javascript 上使用 Regex 工具调试:

此链接包含上面的片段

我究竟做错了什么?

注意 | 所以没有必要有分号。同样在示例中我放了 c,它只是示例中单词的替代品,这就是我使用否定前瞻的原因。

在遵循 Holgers 对使用所有格量词的反应之后,

\"(\S\S+)\";?+(?!c)

它有效, 这是 RegexPlanet 上的链接

4

2 回答 2

2

我相信正则表达式会尽其所能找到匹配项;由于您的表达式说分号可以是可选的,因此它发现它可以匹配整个表达式(因为如果第一组没有使用分号,它就成为否定前瞻的“不匹配”。这与正则表达式工作的递归方式:它一直试图找到一个匹配......

换句话说,这个过程是这样的:

MM:" - matched
(;|) - try semicolon? matched
(?!c) - oops - negative lookahead fails. No match. Go back
(;|)  - try nothing. We still have ';c' left to match
(?!c) - negative lookahead not matched. We have a match 

更新(基于您的评论)。以下代码可能会更好:

\"(\S\S+)\"(;|)((?!c)|(?!;c))

正则表达式可视化

调试演示

于 2013-10-16T02:20:53.807 回答
1

问题是你不想让分号在正则表达式的意义上是可选的。可选分号表示允许匹配器尝试两者,匹配或不匹配。因此,即使分号存在,匹配器也可以忽略它,为组创建一个空匹配,让前瞻成功。

但是如果分号在那里,您想使用它,因此不允许使用它来满足负前瞻。使用 Java 的正则表达式引擎非常简单:使用;?+

这被称为“占有量词”。就像?分号不需要在那里,但如果它在那里,它必须匹配并且不能被忽略。所以正则表达式引擎已经没有其他选择了。

所以整个模式看起来像\"(\S\S+)\";?+(?!c)或者\"(\S\S+)\"(;?+)(?!c)如果你需要一个组中的分号。

于 2013-10-16T10:28:00.730 回答