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


当前回答

我想补充已接受的答案,并用我迟来的答案为讨论作出贡献。

@ChrisVanOpstal分享了这个正则表达式教程,这是学习正则表达式的一个很好的资源。

然而,通读起来确实很耗时。

为了便于记忆,我做了一张备忘单。

这个引用基于每个类前面的大括号[]、()和{},我觉得很容易回忆起来。

Regex = {
 'single_character': ['[]', '.', {'negate':'^'}],
 'capturing_group' : ['()', '|', '\\', 'backreferences and named group'],
 'repetition'      : ['{}', '*', '+', '?', 'greedy v.s. lazy'],
 'anchor'          : ['^', '\b', '$'],
 'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
 'shorthand'       : ['\d', '\w', '\s'],
 }

其他回答

接受的答案很好,但对于正则表达式中缺少简单的子表达式否定运算符来说,这确实是一个解决方案。这就是grep-invert匹配退出的原因。因此,在*nixes中,您可以使用管道和第二个正则表达式来实现所需的结果。

grep 'something I want' | grep --invert-match 'but not these ones'

仍然是一种变通方法,但可能更容易记住。

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

b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]

要做到这一点,一个很好的方法是使用负面展望:

^(?!.*bar).*$

负先行结构是一对括号,左括号后跟问号和感叹号。在lookahead内部[是任何正则表达式模式]。

除非性能是最重要的,否则通常只需通过第二次测试来运行结果,跳过那些与您想要否定的单词相匹配的单词就更容易了。

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

我在尝试为以下英语语句确定正则表达式时遇到了这个论坛主题:

给定一个输入字符串,匹配所有内容,除非该输入字符串正好是“bar”;例如,我想匹配“barrier”和“disbar”以及“foo”。

这是我想出的正则表达式

^(bar.+|(?!bar).*)$

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