【问题标题】:Regex Until But Not Including正则表达式直到但不包括
【发布时间】:2011-04-20 11:43:05
【问题描述】:

对于正则表达式,搜索直到但不包括的语法是什么?有点像:

Haystack:
The quick red fox jumped over the lazy brown dog

Expression:
.*?quick -> and then everything until it hits the letter "z" but do not include z

【问题讨论】:

    标签: regex search regex-lookarounds


    【解决方案1】:

    “搜索到X 但不包括X”的明确表达方式是:

    (?:(?!X).)*
    

    其中X 可以是任何正则表达式。

    不过,在你的情况下,这可能有点矫枉过正——这里最简单的方法是

    [^z]*
    

    这将匹配除z 之外的任何内容,因此在下一个z 之前停止。

    所以.*?quick[^z]* 将匹配The quick fox jumps over the la

    但是,只要您有不止一个简单的字母需要注意,(?:(?!X).)* 就会发挥作用,例如

    (?:(?!lazy).)* - 匹配任何内容,直到单词 lazy 的开头。

    这是使用 lookahead assertion,更具体地说是负前瞻。

    .*?quick(?:(?!lazy).)* 将匹配 The quick fox jumps over the

    说明:

    (?:        # Match the following but do not capture it:
     (?!lazy)  # (first assert that it's not possible to match "lazy" here
     .         # then match any character
    )*         # end of group, zero or more repetitions.
    

    此外,在搜索关键字时,您可能希望用单词边界锚将它们包围:\bfox\b 将仅匹配完整的单词 fox 而不是 foxy 中的狐狸。

    注意

    如果要匹配的文本也可以包含换行符,则需要设置正则表达式引擎的“点匹配所有”选项。通常,您可以通过在正则表达式前面加上 (?s) 来实现,但这并不适用于所有正则表达式引擎(尤其是 JavaScript)。

    替代解决方案:

    在许多情况下,您还可以使用使用惰性量词的更简单、更易读的解决方案。通过将? 添加到* 量词,它将尝试从当前位置匹配尽可能少的字符:

    .*?(?=(?:X)|$)
    

    将匹配任意数量的字符,在X(可以是任何正则表达式)或字符串结尾(如果X 不匹配)之前停止。您可能还需要设置“点匹配所有”选项才能使其正常工作。 (注意:我在X 周围添加了一个非捕获组,以便可靠地将其与交替隔离)

    【讨论】:

    • +1 非常好的答案,不幸的是不适用于grep,但这个answer 可以。
    • @AlexandreLavoie:很有趣。为什么另一个应该工作而不是这个?两者都使用前瞻断言。也许只是因为(?:...) 非捕获组?它可以与((?!X).)* 一起使用吗?
    • 真的不知道,我不是正则表达式专家,也不是 grep。我正在使用grep 过滤来自 sql 中的 mysql bin transformet 的仅一个数据库的请求。这是野兽:grep -Po "(?s)use database_to_keep(.*?)(?=^use)" mysql-bin.000045.sql > filtered.sql
    • 看起来像 bash 冲突,因为当我按下 Up 键时,最后一个命令不是我使用的那个:grep -Po "(?s)use database_to_keep(.*?)(?:(?!^use).)*" mysql-bin.000045.sql > filtered.sql
    • 好编辑,@Tim,只需添加 $ 替代方案:将 .*?(?=X) 替换为 .*?(?=X|$)
    【解决方案2】:

    lookahead regex syntax 可以帮助您实现目标。因此,您的示例的正则表达式是

    .*?quick.*?(?=z)
    

    (?=z) 前瞻之前注意.*? 延迟匹配很重要:表达式匹配子字符串直到第一次 出现z 字母。

    这里是 C# 代码示例:

    const string text = "The quick red fox jumped over the lazy brown dogz";
    
    string lazy = new Regex(".*?quick.*?(?=z)").Match(text).Value;
    Console.WriteLine(lazy); // The quick red fox jumped over the la
    
    string greedy = new Regex(".*?quick.*(?=z)").Match(text).Value;
    Console.WriteLine(greedy); // The quick red fox jumped over the lazy brown dog
    

    【讨论】:

      【解决方案3】:

      试试这个

      (.*?quick.*?)z
      

      【讨论】:

      • 这包括匹配中的“z”,这正是提问者想要避免的。也许正则表达式旨在成为“|”中的一个术语替代,并且该替代正则表达式用于执行多个匹配。如果“z”是一个字符串的开头,该字符串将被替代项中的另一个项匹配,则该匹配项将被取消,因为“z”已被当前匹配项消耗。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-15
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多