正则表达式 - 排除匹配的模式

24

我有以下模式需要排除。

make it cheaper
make it cheapere
makeitcheaper.com.au
makeitcheaper
making it cheaper
www.make it cheaper
ww.make it cheaper.com

我已经创建了一个正则表达式来匹配它们中的任何一个。但是,我想要得到除这些之外的所有内容。我不确定如何反转我创建的这个正则表达式。

mak(e|ing) ?it ?cheaper

上述模式匹配了列出的所有字符串。现在我想让它匹配其他所有内容。我该如何做?

从搜索结果看,似乎我需要类似负向预查/回顾的东西。但是,我真的不太明白。有人能指点我一下吗?

2个回答

37

你可以像这样将其放在负向前瞻中:

(?!mak(e|ing) ?it ?cheaper)

就像那样是不行的,因为如果你使用matches1,它不会匹配,因为你只是在向前查看,实际上没有匹配任何内容,而如果你使用find1,它会多次匹配,因为你可以从许多字符串中的起始位置开始匹配,其中下一个字符与上面的不匹配。

要解决这个问题,根据你想要做什么,我们有两个选择:

  1. 如果你想要排除所有恰好是这些字符串之一的字符串(例如“make it cheaperblahblah”不被排除),则检查字符串的开头(^)和结尾($):

    ^(?!mak(e|ing) ?it ?cheaper$).*
    

    .*(零个或多个通配符)是实际匹配发生的地方。负预查从第一个字符开始检查。

  2. 如果您想要排除所有包含其中之一的字符串,则可以确保在我们匹配每个字符之前不会匹配预查:

  3. ^((?!mak(e|ing) ?it ?cheaper).)*$
    

    另一个选择是在您的预查开头添加通配符(即排除所有从字符串开头包含任何内容的字符串,然后匹配您的模式),但我目前并没有看到任何优势(任意长度的预查也不太可能被任何给定的工具支持):

    ^(?!.*mak(e|ing) ?it ?cheaper).*
    

由于使用了 ^$,因此无论是使用 find 还是 matches 都适用于上述任何一种情况(尽管在使用 matches 时,^ 是可选的,在使用 find 时,位于环视外部的 .* 是可选的)。


1:虽然它们可能没有这个名称,但许多语言都有等效于带有正则表达式的 matchesfind 的函数。


以上是针对此问题的严格正则表达式答案。

更好的方法可能是坚持原始的正则表达式(mak(e|ing) ?it ?cheaper),并查看是否可以直接使用您正在使用的工具或语言来否定匹配项。

例如,在 Java 中,这将涉及执行 if (!string.matches(originalRegex))(请注意 !,该符号否定了返回的布尔值),而不是执行 if (string.matches(negLookRegex))


9
我认为你需要的是负向先行断言。可以尝试使用以下代码:

负向先行断言,我相信这正是你要找的。也许可以试试:

(?!.*mak(e|ing) ?it ?cheaper)

也许需要更加灵活:

(?!.*mak(e|ing) *it *cheaper)

防止出现多个空格。


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