RegEx - 排除匹配模式

San*_*San 15 regex negative-lookahead lookaround regex-lookarounds

我有以下模式被排除在外.

make it cheaper
make it cheapere
makeitcheaper.com.au
makeitcheaper
making it cheaper
www.make it cheaper
ww.make it cheaper.com
Run Code Online (Sandbox Code Playgroud)

我创建了一个正则表达式以匹配其中任何一个.但是,除了这些之外,我还希望得到其他所有东西.我不知道如何逆转我创建的这个正则表达式.

mak(e|ing) ?it ?cheaper
Run Code Online (Sandbox Code Playgroud)

上面的模式匹配列出的所有字符串.现在我想让它与其他一切相匹配.我该怎么做?

从搜索来看,似乎我需要像负向前瞻/回顾这样的东西.但是,我真的不明白.有人能指出我正确的方向吗?

Duk*_*ing 26

你可以把它放在负面的预测中,如下所示:

(?!mak(e|ing) ?it ?cheaper)
Run Code Online (Sandbox Code Playgroud)

就像那样不会起作用,因为,如果你做matches1,它将不匹配,因为你只是向前看,你实际上没有匹配任何东西,并且,如果你做find1,它将匹配很多时候,因为你可以从字符串中的许多地方开始,下一个字符与上面的字符不匹配.

要解决这个问题,根据您的意愿,我们有两个选择:

  1. 如果你想排除那些恰好其中之一的所有字符串(即"make it cheaperblahblah"不被排除),检查字符串的start(^)和end($):

    ^(?!mak(e|ing) ?it ?cheaper$).*
    
    Run Code Online (Sandbox Code Playgroud)

    .*(零个或多个野生卡)是实际匹配的发生.来自第一个角色的负向前瞻检查.

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

    ^((?!mak(e|ing) ?it ?cheaper).)*$
    
    Run Code Online (Sandbox Code Playgroud)

    另一种方法是在你的预测开始时添加通配符(即排除从字符串开头包含任何内容,然后是你的模式的所有字符串),但我目前看不到任何优势(任意给定工具也不太可能支持任意长度前瞻:

    ^(?!.*mak(e|ing) ?it ?cheaper).*
    
    Run Code Online (Sandbox Code Playgroud)

因为^$,或者为上述任何一个做一个find或者一个matches将工作(但是,在这种情况下matches,^是可选的find,在.*外部情况下,前瞻是可选的).


1:虽然他们可能没有被称为是,很多语言都等同于功能matchesfind使用正则表达式.


以上是这个问题的严格正则表达式的答案.

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

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


Jer*_*rry 8

负面的前瞻,我相信是你正在寻找的.也许试试:

(?!.*mak(e|ing) ?it ?cheaper)
Run Code Online (Sandbox Code Playgroud)

也许更灵活一点:

(?!.*mak(e|ing) *it *cheaper)
Run Code Online (Sandbox Code Playgroud)

以防有多个空间.