当我尝试这个正则表达式时
\"(\S\S+)\"(?!;c)
在这个字符串上“MM:”; d 它符合我想要的匹配
并且在此字符串上“MM:”; c 它与所需内容不匹配。
但是当我添加第二组时,通过移动该组中的分号并使用|
使其成为可选项\"(\S\S+)\"(;|)(?!c)
这个字符串“MM:”; c 当我预期它不喜欢之前它匹配。
我在Java上尝试了这个,然后在Javascript上使用Regex工具debuggex:
This link contains a snippet of the above
我做错了什么?
注意|因此没有必要有分号。在我放c的例子中,它只是一个单词的例子中的替代品,这就是我使用负向前瞻的原因。
遵循Holgers对使用占有量词的回应,
\"(\S\S+)\";?+(?!c)
答案 0 :(得分: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))
答案 1 :(得分:1)
问题是你不想在正则表达式的意义上使分号成为可选的。一个可选的分号意味着匹配器可以尝试两者,匹配或不匹配。因此,即使分号在那里,匹配器也可以忽略它为该组创建一个空匹配,让前瞻成功。
但是如果它在那里你想要使用分号,所以不允许它用于满足负前瞻。使用Java的正则表达式引擎非常简单:使用;?+
这被称为“占有量词”。与?
一样,分号不需要在那里但是如果它在那里它必须匹配且不能被忽略。所以正则表达式引擎已经没有其他选择了。
如果您需要分组中的分号,整个模式看起来像\"(\S\S+)\";?+(?!c)
或\"(\S\S+)\"(;?+)(?!c)
。