正则表达式的否定?

18

我正在玩正则表达式高尔夫(http://regex.alf.nu/),并且正在进行Abba游戏。我有以下匹配错误方面的正则表达式(这正是我想要做的):

(([\w])([\w])\3\2)

然而,我现在正试图否定它以使其与另一侧匹配。但是我似乎无法理解那部分。我尝试了:

(?!([\w])([\w])\3\2)

但那行不通。有正则表达式大师的任何提示吗?


错误的一面?哪一面?请提供完整的上下文。 - gitaarik
3个回答

24

只需使用 . 并删除不必要的括号,即可将其缩短(并获得更多分数)。

^(?!.*(.)(.)\2\1)

它只是确保字符串的任何部分中没有“abba”(“abba”在这里指特定顺序的4个字母,我们不想匹配整个单词)而无需匹配整个单词。


我知道这很老了,但你能解释一下 ?! 是如何工作的吗?更具体地说,为什么 (?!(.)(.)\2\1) 匹配所有内容。 - Adi Bradfield
1
@AdiBradfield (?!a)a 永远不会匹配任何内容,因为在 (?! ... ) 组之后有一个 a,而 (?!a) 防止匹配如果在其后面有 a(内部的内容)。同样,(?!a)b 将始终匹配 b,因为虽然 (?!a) 防止匹配如果其后跟着 a,但这永远不会发生,因为在其后面有一个 b。扩展到 ^(?!.*a),如果任何行包含 a,则将防止匹配。锚点和 .* 很重要,否则模式将开始匹配可能存在的任何 a(因为在那一点之后,没有更多的 a 来防止匹配)。 - Jerry
好的,没问题,那很有道理。谢谢你的澄清。 - Adi Bradfield
1
@Zikato 它正在工作;正则表达式只是匹配一个空行,如果你只是检查是否匹配,那么这并不重要,请参见http://i.stack.imgur.com/5MzvR.png。 - Jerry

2
这里的关键是前导符号^和.*。
(?! ...) 是一个前瞻构造,因此不会推进正则表达式处理引擎。
单独使用 / (?! ...)/ 将正确地返回不匹配表达式中的项的负结果;但是对于不匹配(...)的项,正则表达式引擎将继续处理。然而,如果您的正则表达式只包含 (?! ),那么没有剩余内容需要处理,正则表达式处理位置永远不会向前移动。(请参见这个很好的答案)。
显然,由于剩余的正则表达式为空,它匹配字符串的任何零宽度段,即它匹配任何字符串。
[begin SWAG]
有了插入符号^,正则表达式引擎能够识别您正在寻找真正的答案,并且您不希望它告诉您该字符串包含零宽度组件。
[end SWAG]
因此,当 (?! ) 成功时,它能够正确地无法匹配。

2
为了使你的SWAG更加精确,脱字符(^)不允许引擎查找不在字符串开头的零长度匹配。 - RHH

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接