如何否定正则表达式中的特定单词?

Bos*_*one 594 regex

我知道我可以否定一组字符,[^bar]但是我需要一个正则表达式,其中否定适用于特定的单词 - 所以在我的例子中我如何否定实际bar而不是[^bar]

Chr*_*tal 657

一个很好的方法是使用负向前瞻:

^(?!.*bar).*$
Run Code Online (Sandbox Code Playgroud)

负前瞻构造是一对括号,左括号后跟一个问号和一个感叹号.在前瞻内部[是任何正则表达式模式].

  • 不幸的是,这不适用于所有语言. (38认同)
  • 这说明了一切(我可能会开始使用(?!bar)并建立起来).我不明白为什么其他人会这么复杂. (10认同)
  • 一开始的行开头角色确实很不错. (5认同)
  • 做得很好 - 匹配一个具有指定字符串的行,字符串前面没有任何东西,字符串后跟任何东西.根据定义,这是字符串的缺失!因为如果它存在,即使它是一个线锚^,它总是会有一些东西 (2认同)
  • @NeilTraft`grep -v bar` :) (2认同)
  • 如果您使用的是 grep,则使用 -P 选项。-P 启用 perl 正则表达式。例如 grep -P '(?! 不包含这个字符串)' (2认同)
  • 不幸的是,这不适用于实际的单词。`foo` 会匹配,`bar` 不会,但 `foobar` 或 `barfoo` 也不会! (2认同)

Bry*_*ley 60

除非性能是最重要的,否则通过第二遍传递结果通常更容易,跳过那些与你想要否定的词匹配的结果.

正则表达式通常意味着您正在编写脚本或某种低性能任务,因此找到易于阅读,易于理解且易于维护的解决方案.

  • 在很多情况下,您无法控制工作流程:您只需编写一个过滤器的正则表达式. (7认同)

JAB*_*JAB 44

以下正则表达式将执行您想要的操作(只要支持负面的lookbehinds和前瞻),正确匹配的东西; 唯一的问题是它匹配单个字符(即每个匹配是单个字符而不是两个连续"条"之间的所有字符),如果你使用非常长的字符串,可能会导致高额开销.

b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]
Run Code Online (Sandbox Code Playgroud)

  • 我写这个答案已经两年半了,但是肯定的. (13认同)
  • 而不是那些迫使我们在得到你的最终答案之前阅读错误答案的多次更新,为什么不重写你的答案是完整的,但没有有些混乱的坏部分?如果有人真正关心编辑历史,他们可以使用本网站的内置功能. (7认同)
  • 该死的,试试这个(?:(?!bar).)* (3认同)

Gum*_*mbo 43

您可以使用负面预测或后视:

^(?!.*?bar).*
^(.(?<!bar))*?$
Run Code Online (Sandbox Code Playgroud)

或者只使用基础知识:

^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$
Run Code Online (Sandbox Code Playgroud)

这些都匹配任何不包含的东西bar.

  • 我认为要点的是,看看你的模式,你所做的一切都是拒绝"bar"这个词,这一点都不清楚. (5认同)
  • `(?:[^ B] [^一个] [^ R])*` (4认同)

小智 30

我在尝试识别以下英语声明的正则表达式时遇到了这个论坛帖子:

给定输入字符串,匹配所有内容, 除非此输入字符串正好是'bar'; 例如,我想匹配'barrier'和'disbar'以及'foo'.

这是我提出的正则表达式

^(bar.+|(?!bar).*)$
Run Code Online (Sandbox Code Playgroud)

正则表达式的英文翻译是"匹配字符串,如果它以'bar'开头,并且它至少有一个其他字符,或者字符串不以'bar'开头.

  • `^(?! bar $)。*`与此匹配(除完全`bar`之外的所有东西),并避免重复。 (4认同)
  • 那就是我要找的人。它真的很适合除了酒吧之外的所有东西。 (2认同)

sgr*_*lon 29

解:

^(?!.*STRING1|.*STRING2|.*STRING3).*$
Run Code Online (Sandbox Code Playgroud)

xxxxxx 好的

xxxSTRING1xxx KO(是否需要)

xxxSTRING2xxx KO(是否需要)

xxxSTRING3xxx KO(是否需要)

  • 我是唯一一个讨厌“OK”和“KO”作为通过考试指标的人吗?只差一个错别字就酿成大祸了…… (8认同)
  • 谢谢,这给了我多个单词所需的额外信息 (2认同)

Gre*_*ell 12

接受的答案很好,但实际上是在正则表达式中缺少一个简单的子表达式否定运算符.这就是grep --invert-match退出的原因.所以在*nixes中,你可以使用管道和第二个正则表达式来完成所需的结果.

grep 'something I want' | grep --invert-match 'but not these ones'
Run Code Online (Sandbox Code Playgroud)

仍然是一种解决方法,但也许更容易记住.


lev*_*tov 11

摘自bkDJ评论

^(?!bar$).*
Run Code Online (Sandbox Code Playgroud)

该解决方案的优点是可以明确否定(排除)多个单词:

^(?!bar$|foo$|banana$).*
Run Code Online (Sandbox Code Playgroud)

  • 为什么需要尾随“.*”? (9认同)

Boo*_*boo 9

如果它确实是一个您不想匹配的单词,那么:bar

^(?!.*\bbar\b).*$
Run Code Online (Sandbox Code Playgroud)

上面的代码将匹配任何不包含bar单词边界上的字符串,也就是说,与非单词字符分开。但是,除非使用正确的正则表达式标志,否则上述模式中使用的句点/点 ( .) 将不会匹配换行符:

^(?s)(?!.*\bbar\b).*$
Run Code Online (Sandbox Code Playgroud)

或者:

^(?!.*\bbar\b)[\s\S]*$
Run Code Online (Sandbox Code Playgroud)

我们不使用任何特殊标志,而是查找任何空白或非空白字符。这应该涵盖每个角色。

但是,如果我们想要匹配可能包含bar但不是特定单词的单词怎么办bar

(?!\bbar\b)\b\[A-Za-z-]*bar[a-z-]*\b
Run Code Online (Sandbox Code Playgroud)
  1. (?!\bbar\b) Assert that the next input is not bar on a word boundary.
  2. \b\[A-Za-z-]*bar[a-z-]*\b Matches any word on a word boundary that contains bar.

See Regex Demo