正则表达式中的(?!)运算符如何工作?

时间:2013-08-15 09:40:23

标签: javascript regex

我以为我理解正则表达式运算符是如何工作的,但现在我真的很困惑。 在简化示例中,我有两个字符串:

mail.wow.no-1.com
mail.ololo.wow.com

我想匹配第一个,而不是第二个。 我正在写这样的正则表达式(简化版):

^mail\.(.*)(?!\.wow\.com)$

当我在这两个例子的JS方法测试中运行时,它只返回true(在sublime 2正则表达式搜索中突出显示两个字符串,这意味着两个字符串匹配)

我知道我可以制作反向正则表达式,它将匹配第二个并根据此制作逻辑,但我只是想了解正则表达式中的(?!)如何工作以及我做错了什么。

感谢。

4 个答案:

答案 0 :(得分:8)

您需要在前瞻中找到.*(并将其移到前瞻之外的.*前面):

^mail(?!.*\.wow\.com)\.(.*)$

否则,您的前瞻只会检查字符串的末尾。显然,在字符串的末尾,永远不会有.wow.com。您现在也可以将前瞻移动到模式的开头:

^(?!.*\.wow\.com)mail\.(.*)$

Working demo.

这最后一个变体的效率稍差,但如果影响整个字符串的前瞻一切都在模式的开头,我发现模式更容易阅读。

答案 1 :(得分:3)

这是一个zero width assertion。这是一个负面的展望。

它说的是:在这个位置 - 以下不可能来。

因此,例如(?!q)表示,字母q现在无法跟进。

答案 2 :(得分:3)

你想要的是

^mail\.(?!.*\.wow\.com$).*$

正如其他人所说,(?!)是一个负零宽度前瞻断言;它与任意数量的字符都不匹配,但会看到下一个字符,并确保它们与括号中包含的字符不匹配。

Javascript从Perl复制了正则表达式语法;这些通常称为PCRE,或Perl兼容的正则表达式;然而,Javascript只有前瞻性,即他们从这一点看到了未来; Perl也具有负零宽度后视,它可以像原始示例一样工作,在这种情况下更容易

# this is how it could be done in Perl
^mail\..*(?<!\.wow\.com)$

然而,Javascript选择不支持lookbehinds。

答案 3 :(得分:1)

对此网址的检查是它查找“邮件”。然后尽可能多的字符,然后检查是否存在(即字符串的结尾)和屏幕的结尾,如果“.wow.com”存在。

^mail\.(.*)(?!\.wow\.com)$

相反,请对其进行重新排序,以便检查“.wow.com”是否位于“mail”之后。

^mail\.(?!.*\.wow\.com)(.*)$