【问题标题】:What do 'lazy' and 'greedy' mean in the context of regular expressions?在正则表达式的上下文中,“懒惰”和“贪婪”是什么意思?
【发布时间】:2011-01-19 01:36:01
【问题描述】:

这两个术语是什么意思?

【问题讨论】:

标签: regex regex-greedy non-greedy


【解决方案1】:

Greedy 意味着您的表达式将匹配尽可能大的组,lazy 意味着它将匹配尽可能小的组。对于这个字符串:

abcdefghijklmc

还有这个表达式:

a.*c

贪婪匹配会匹配整个字符串,而惰性匹配只会匹配第一个abc。

【讨论】:

    【解决方案2】:

    'Greedy' 表示匹配最长的字符串。

    'Lazy' 表示匹配最短的可能字符串。

    例如,贪婪的h.+l 匹配'hello' 中的'hell',但懒惰的h.+?l 匹配'hel'。

    【讨论】:

    • 太棒了,所以lazy会在条件l满足时停止,而greedy意味着只有在条件l不再满足时才会停止?
    • 对于所有阅读帖子的人:贪婪或懒惰的量词本身不会匹配最长/最短的子字符串。您必须使用tempered greedy token,或使用非正则表达式方法。
    • @AndrewS 不要被示例中的双 ll 混淆。它相当懒惰会匹配尽可能短的子串,而贪婪会匹配尽可能长的子串。贪婪的h.+l 匹配'helolo' 中的'helol',但懒惰的h.+?l 匹配'hel'。
    • @FloatingRock: 否。x? 表示 x 是可选的,但 +? 是不同的语法。这意味着停止寻找匹配的东西 - 惰性匹配。
    • @FloatingRock:至于如何区分不同的语法,很简单:? 表示可选,+? 表示懒惰。因此\+? 表示+ 是可选的。
    【解决方案3】:

    来自Regular expression

    常规中的标准量词 表达式是贪婪的,这意味着它们 尽可能匹配,只给予 根据需要返回以匹配 正则表达式的其余部分。

    通过使用惰性量词, 表达式尝试最小匹配 首先。

    【讨论】:

      【解决方案4】:

      贪婪会尽可能多地消耗。在http://www.regular-expressions.info/repeat.html 中,我们看到了尝试将HTML 标记与<.+> 匹配的示例。假设您有以下内容:

      <em>Hello World</em>
      

      您可能认为&lt;.+&gt;(. 表示任何非换行符,+ 表示一个或多个)只会匹配&lt;em&gt; 和&lt;/em&gt;,实际上它会非常贪婪,从第一个&lt;到最后一个&gt;。这意味着它将匹配 &lt;em&gt;Hello World&lt;/em&gt; 而不是您想要的。

      让它变得懒惰 (&lt;.+?&gt;) 可以防止这种情况发生。通过在+ 之后添加?,我们告诉它重复尽可能少的次数,所以它遇到的第一个&gt; 是我们要停止匹配的地方。

      我鼓励您下载 RegExr,这是一个可以帮助您探索正则表达式的好工具 - 我一直都在使用它。

      【讨论】:

      • 所以如果你使用 greedy,你会有 3 个(1 个元素 + 2 个标签)匹配还是只有 1 个匹配(1 个元素)?
      • 只会匹配1次,从第一个开始,到最后一个>结束。
      • 但是让它变得懒惰会匹配两次,给我们打开和关闭标签,忽略中间的文本(因为它不适合表达式)。
      • 只是补充一点,也有一种贪婪的方法:&lt;[^&gt;]+&gt;regex101.com/r/lW0cY6/1
      • 作为记录,关于在 HTML 中使用正则表达式 stackoverflow.com/questions/1732348/…
      【解决方案5】:

      取自www.regular-expressions.info

      贪婪:贪婪量词首先尝试重复标记多次 尽可能,并随着引擎回溯寻找而逐渐放弃匹配 整体匹配。

      惰性:惰性量词首先根据需要重复标记几次,然后 随着引擎通过正则表达式回溯到 找到一个整体匹配。

      【讨论】:

      • 与投票率较高的答案相比,这似乎是“懒惰”的最正确定义。其他答案似乎忽略了引擎“逐渐扩展匹配......以找到整体匹配”的概念。
      【解决方案6】:
      Greedy quantifier Lazy quantifier Description
      * *? Star Quantifier: 0 or more
      + +? Plus Quantifier: 1 or more
      ? ?? Optional Quantifier: 0 or 1
      {n} {n}? Quantifier: exactly n
      {n,} {n,}? Quantifier: n or more
      {n,m} {n,m}? Quantifier: between n and m

      添加一个?到一个量词,使其变得不贪婪,即懒惰。

      示例:
      测试字符串:stackoverflow
      贪婪 reg 表达式:s.*o 输出:stackoverflow
      惰性 reg 表达式 em>:s.*?o 输出:stackoverflow

      【讨论】:

      • 不是??相当于 ? .同样,不是 {n} 吗?相当于 {n}
      • @BreakingBenjamin:不??不等于?,当它可以选择返回 0 或 1 时,它将选择 0(惰性)替代方案。要查看差异,请将re.match('(f)?(.*)', 'food').groups() 与re.match('(f)??(.*)', 'food').groups() 进行比较。在后者中,(f)?? 不会匹配前导的“f”,即使它可以匹配。因此,'f' 将与第二个 '.*' 捕获组匹配。我相信你可以用 '{n}?' 构造一个例子?也。诚然,这两个很少使用。
      • @Number945 是的,{n}? 等价于 {n}。见stackoverflow.com/questions/18006093/how-do-an-and-an-differ
      【解决方案7】:

      尝试理解以下行为:

          var input = "0014.2";
      
      Regex r1 = new Regex("\\d+.{0,1}\\d+");
      Regex r2 = new Regex("\\d*.{0,1}\\d*");
      
      Console.WriteLine(r1.Match(input).Value); // "0014.2"
      Console.WriteLine(r2.Match(input).Value); // "0014.2"
      
      input = " 0014.2";
      
      Console.WriteLine(r1.Match(input).Value); // "0014.2"
      Console.WriteLine(r2.Match(input).Value); // " 0014"
      
      input = "  0014.2";
      
      Console.WriteLine(r1.Match(input).Value); // "0014.2"
      Console.WriteLine(r2.Match(input).Value); // ""
      

      【讨论】:

      • 这是什么语言?
      • 他使用的语言是C#
      【解决方案8】:

      据我所知,大多数正则表达式引擎默认是贪婪的。在量词末尾添加一个问号将启用惰性匹配。

      正如@Andre S 在评论中提到的那样。

      • 贪婪:继续搜索直到条件不满足。
      • 懒惰:一旦满足条件就停止搜索。

      什么是贪婪,什么是懒惰,请参考下面的例子。

      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      public class Test {
          public static void main(String args[]){
              String money = "100000000999";
              String greedyRegex = "100(0*)";
              Pattern pattern = Pattern.compile(greedyRegex);
              Matcher matcher = pattern.matcher(money);
              while(matcher.find()){
                  System.out.println("I'm greeedy and I want " + matcher.group() + " dollars. This is the most I can get.");
              }
      
              String lazyRegex = "100(0*?)";
              pattern = Pattern.compile(lazyRegex);
              matcher = pattern.matcher(money);
              while(matcher.find()){
                  System.out.println("I'm too lazy to get so much money, only " + matcher.group() + " dollars is enough for me");
              }
          }
      }
      


      结果是:
      I'm greeedy and I want 100000000 dollars. This is the most I can get.
      
      I'm too lazy to get so much money, only 100 dollars is enough for me
      

      【讨论】:

        【解决方案9】:

        贪婪匹配。 正则表达式的默认行为是贪婪。这意味着它会尝试尽可能多地提取,直到它符合某种模式,即使较小的部分在语法上就足够了。

        示例:

        import re
        text = "<body>Regex Greedy Matching Example </body>"
        re.findall('<.*>', text)
        #> ['<body>Regex Greedy Matching Example </body>']
        

        它不是匹配直到第一次出现“>”,而是提取整个字符串。这是正则表达式的默认贪婪或“通吃”行为。

        延迟匹配,另一方面,“尽可能少”。这可以通过在模式末尾添加? 来实现。

        示例:

        re.findall('<.*?>', text)
        #> ['<body>', '</body>']
        

        如果您只想检索第一个匹配项,请改用搜索方法。

        re.search('<.*?>', text).group()
        #> '<body>'
        

        来源:Python Regex Examples

        【讨论】:

          【解决方案10】:

          贪婪意味着它会消耗你的模式,直到它们都不剩并且它不能再看下去了。

          Lazy 会在遇到您请求的第一个模式时立即停止。

          我经常遇到的一个常见示例是正则表达式([0-9]{2}\s*-\s*?[0-9]{7}) 的\s*-\s*?

          第一个\s* 因为* 而被归类为贪婪,并且在遇到数字后会尽可能多地查找空格,然后查找破折号“-”。第二个\s*? 是懒惰的,因为*? 的存在意味着它会看起来是第一个空白字符并停在那里。

          【讨论】:

          • 我不明白该正则表达式与不使用惰性量词有何不同。 \s 只能匹配一个空格,并且要求后面有 7 位数字。
          【解决方案11】:

          最好的例子。细绳。 192.168.1.1 和一个贪婪的正则表达式 \b.+\b 您可能认为这会给您第一个八位字节,但实际上匹配整个字符串。为什么?因为.+ 是贪心的,贪心匹配匹配192.168.1.1 中的每个字符,直到它到达字符串的末尾。这是重要的一点!现在它开始一次回溯一个字符,直到找到第三个标记 (\b) 的匹配项。

          如果字符串是一个 4GB 的文本文件和 192.168.1.1,那么您可以很容易地看到这种回溯将如何导致问题。

          要使正则表达式不贪心(懒惰),请在贪心搜索后加上问号,例如

          *?
          ??
          +?
          

          现在发生的是令牌 2 (+?) 找到匹配项,正则表达式沿字符移动,然后尝试下一个令牌 (\b) 而不是令牌 2 (+?)。所以它小心翼翼地爬行。

          【讨论】:

            【解决方案12】:

            贪婪量词就像 IRS/ATO

            如果它在那里,他们会全部拿走。

            IRS 与此正则表达式匹配:.*

            $50,000

            这将匹配所有内容!

            查看示例:Greedy-example

            非贪婪量词 - 他们尽可能少地使用

            如果我要求退税,国税局突然变得不贪婪,他们使用这个量词:

            (.{2,5}?)([0-9]*) 反对这个输入:$50,000

            第一组是非需要的,只匹配$5——所以我得到了$5 50,000 美元输入的退款。他们不贪婪。他们尽可能地少。

            请看这里:Non-greedy-example。

            何必呢?

            如果您尝试匹配表达式的某些部分,这一点就变得很重要。有时您不想匹配所有内容。

            希望这个类比能帮助你记住!

            【讨论】:

              猜你喜欢
              • 2012-11-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多