【问题标题】:Match everything except for specified strings匹配除指定字符串之外的所有内容
【发布时间】:2011-01-25 03:07:39
【问题描述】:

我知道以下正则表达式将匹配“红色”、“绿色”或“蓝色”。

red|green|blue

有没有一种简单的方法让它匹配所有除了几个指定的字符串?

【问题讨论】:

  • 不是所有的正则表达式都能做到这一点。你在什么环境下工作?爪哇?珀尔? 。网?一些 C/C++ 正则表达式库?关系数据库管理系统?
  • 你没有说你想要什么,但你可以简单地颠倒“匹配”操作的意义。如果您尝试对不匹配的部分进行提取,这对您没有帮助,但要测试排除的字符串是否不存在,它会起作用:if (!s.match(/red|green|blue/)) ... 注意:我知道 OP 没有指定什么语言/框架,所以前面的例子应该被认为是一个通用的例子,而不是一个规定的例子。

标签: regex


【解决方案1】:

如果你想确保字符串既不是红色、绿色也不是蓝色,caskey's answer 就是它。然而,通常需要的是确保行中的任何地方都不包含红色、绿色或蓝色。为此,使用^ 锚定正则表达式并在否定前瞻中包含.*

^(?!.*(red|green|blue))

另外,假设您想要包含单词“engine”但没有任何颜色的行:

^(?!.*(red|green|blue)).*engine

您可能认为可以将 .* 分解到正则表达式的头部:

^.*(?!red|green|blue)engine     # Does not work

但你不能。您必须同时拥有.* 的两个实例才能使其工作。

【讨论】:

  • 重要的是,前瞻不是 BRE(基本)或 ERE(扩展)正则表达式的一部分。您需要 PCRE(Perl 兼容)或类似的。 ------ 您的最后一个示例不起作用,因为开头的贪婪 .* 将匹配任何内容。您需要使初始匹配更具体。例如只匹配空格:printf 'redengine\nblackengine\ngreenengine\n' | grep -P '^\s*(?!red|green|blue)\w*engine'
【解决方案2】:

取决于语言,但通常可以这样输入否定断言:

(?!red|green|blue)

(感谢语法修复,以上是有效的 Java 和 Perl,YMMV)

【讨论】:

  • @caskey,完整的答案是我和你的结合。如果您想将它们合并在一起,我将删除我的。
  • 如果您稍微解释一下,这个答案会更有用。例如:什么是“?”和 ”!”意思是?为什么需要捕获组?
  • 它也是有效的 Python。
  • 刚刚将它与 Delphi regEx 库一起使用,它只能像这样工作:^(?!red|green|blue)。在 regex101.com 上测试它也是如此。那么上面的错字是否缺少 ^ 或者它实际上是否像 Java/Perl/Python .. 中那样工作?
  • 我很好奇@Lii评论的答案
【解决方案3】:

匹配除给定字符串之外的任何内容

如果你想匹配整个字符串,你想匹配除某些字符串之外的所有内容,你可以这样做:

^(?!(red|green|blue)$).*$

这就是说,从字符串的开头开始匹配,它不能以红色、绿色或蓝色开始和结束,并将其他任何东西匹配到字符串的末尾。

你可以在这里试试:https://regex101.com/r/rMbYHz/2

请注意,这只适用于支持 negative lookahead 的正则表达式引擎。

【讨论】:

    【解决方案4】:

    您不需要负前瞻。有工作示例:

    /([\s\S]*?)(red|green|blue|)/g
    

    说明:

    • [\s\S] - 匹配任意字符
    • * - 匹配从 0 到前一组的无限制
    • ? - 尽可能少匹配
    • (red|green|blue|) - 匹配其中一个词或不匹配
    • g - 重复模式

    例子:

    whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

    将是:

    whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

    测试一下:regex101.com

    【讨论】:

    • 您可以通过将 [\s\S] 换成一个点来大幅减少步数。我很困惑为什么看似每个其他示例都单独捕获每个单词。这种方式稍微多一些正则表达式步骤,但需要的后处理要少得多。
    • 但这不会进行匹配(文本验证),它只是在替换期间删除指定的文本。
    • 此解决方案不会在已知单词之后输出最后的文本块。所以,没有必要比较速度,这是错误的。
    • @WiktorStribiżew 已修复。
    【解决方案5】:

    我有同样的问题,提出的解决方案几乎可以正常工作,但存在一些问题。最后我使用的正则表达式是:

    ^(?!red|green|blue).*
    

    我在 Javascript 和 .NET 中对其进行了测试。

    .* 不应该像这样放在负前瞻中:^(?!.*red|green|blue) 否则它会使第一个元素的行为与其余元素不同(即“anotherred”不会是匹配而“另一个绿色”会)

    【讨论】:

      【解决方案6】:

      匹配任何文本,但匹配模式的文本通常通过分割正则表达式模式的字符串来实现。

      例子

      • - Regex.Split(text, @"red|green|blue") 或者,为了摆脱空值,Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(参见demo
      • - Regex.Split(text, "red|green|blue") 或者,要删除空项目,Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(请参阅 demothis demo,其中支持 LINQ)
      • - text.split(/red|green|blue/)(此处无需使用g 修饰符!)(要删除空值,请使用text.split(/red|green|blue/).filter(Boolean)),请参阅demo
      • - text.split("red|green|blue"),或 - 保留所有尾随的空项目 - 使用 text.split("red|green|blue", -1),或删除所有空项目使用 more code to remove them(请参阅 demo
      • - 类似于 Java,text.split(/red|green|blue/),获取所有尾随项​​目使用 text.split(/red|green|blue/, -1) 并删除所有空项目使用 text.split(/red|green|blue/).findAll {it != ""})(参见 demo
      • - text.split(Regex("red|green|blue")) 或者,要删除空白项目,请使用 text.split(Regex("red|green|blue")).filter{ !it.isBlank() },请参阅 demo
      • - text.split("red|green|blue"),或者要保留所有尾随的空项目,请使用text.split("red|green|blue", -1),要删除所有空项目,请使用text.split("red|green|blue").filter(_.nonEmpty)(请参阅demo
      • - text.split(/red|green|blue/),要删除空值,请使用 .split(/red|green|blue/).reject(&:empty?)(要同时获取前导和尾随空项,请使用 -1 作为第二个参数,.split(/red|green|blue/, -1))(请参阅 demo)李>
      • - my @result1 = split /red|green|blue/, $text;,或带有所有尾随空项,my @result2 = split /red|green|blue/, $text, -1;,或不带任何空项,my @result3 = grep { /\S/ } split /red|green|blue/, $text;(请参阅demo
      • - preg_split('~red|green|blue~', $text)preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY) 不输出空项目(参见demo
      • - re.split(r'red|green|blue', text) 或者,要删除空项目,list(filter(None, re.split(r'red|green|blue', text)))(请参阅 demo
      • - 使用regexp.MustCompile("red|green|blue").Split(text, -1),如果需要删除空项目,使用this code。见Go demo

      注意:如果您的模式包含capturing groups,则正则表达式拆分函数/方法may 的行为会有所不同,这也取决于其他选项。请参考相应的拆分方法文档。

      【讨论】:

        【解决方案7】:

        除了单词“red”之外的所有内容

        var href = '(text-1) (red) (text-3) (text-4) (text-5)';
        
        var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 
        
        function testF(match, p1, p2, offset, str_full) {
          p1 = "-"+p1+"-";
          return p1;
        }
        
        console.log(test);

        除了单词“red”之外的所有内容

        var href = '(text-1) (frede) (text-3) (text-4) (text-5)';
        
        var test = href.replace(/\(([\s\S]*?)\)/g, testF); 
        
        function testF(match, p1, p2, offset, str_full) {
          p1 = p1.replace(/red/g, '');
          p1 = "-"+p1+"-";
          return p1;
        }
        
        console.log(test);

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-03
          • 1970-01-01
          • 1970-01-01
          • 2013-12-22
          • 1970-01-01
          相关资源
          最近更新 更多