6

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

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

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

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

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

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

谢谢。

4

4 回答 4

8

您需要一个.*内部的前瞻(并将其移动到前瞻外部的前面.*):

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

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

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

工作演示。

最后一个变体的效率略低,但如果影响整个字符串的前瞻都位于模式的开头,我发现模式更容易阅读。

于 2013-08-15T09:43:02.930 回答
3

这是一个零宽度断言。这是一种消极的展望。

它说什么:在这个位置 - 以下不能来。

因此,例如(?!q)意味着,该字母q现在不能跟随。

于 2013-08-15T09:42:32.423 回答
3

你想要的是

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

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

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

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

然而 Javascript 已经选择不支持后视。

于 2013-08-15T09:55:45.920 回答
1

对这个 url 的检查是它寻找“邮件”。然后尽可能多的字符,然后检查是否存在(即字符串的结尾)和屏幕结尾之间是否存在“.wow.com”。

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

相反,重新排序它以检查“.wow.com”是否在“mail.”之后。

^mail\.(?!.*\.wow\.com)(.*)$
于 2013-08-15T09:45:50.660 回答