代码之家  ›  专栏  ›  技术社区  ›  jjnguy Julien Chastang

“贪婪”和“不情愿”正则表达式量词有什么区别?

  •  22
  • jjnguy Julien Chastang  · 技术社区  · 15 年前

    Pattern javadocs:

    Greedy quantifiers:
    X?      X, once or not at all  
    X*      X, zero or more times  
    X+      X, one or more times  
    X{n}    X, exactly n times  
    X{n,}   X, at least n times  
    X{n,m}  X, at least n but not more than m times
    
    Reluctant quantifiers:
    X??     X, once or not at all  
    X*?     X, zero or more times  
    X+?     X, one or more times  
    X{n}?   X, exactly n times  
    X{n,}?  X, at least n times  
    X{n,m}? X, at least n but not more than m times
    

    他们所做的描述是一样的……那么,有什么区别呢?

    我真的很欣赏一些例子。

    我在Java中编码,但是我听说这个概念对于大多数现代ReGEX实现是一样的。

    5 回复  |  直到 10 年前
        1
  •  37
  •   PatrikAkerstrand    15 年前

    贪婪的操作符总是试图“抓住”尽可能多的输入,而不情愿的量词将尽可能少的匹配输入,并且仍然创建匹配。

    例子:

    "The red fox jumped over the red fence"
    /(.*)red/ => \1 = "The red fox jumped over the "
    /(.*?)red/ => \1 = "The "
    
    "aaa"
    /a?a*/ => \1 = "a", \2 = "aa"
    /a??a*/ => \1 = "", \2 = "aaa"
    
    "Mr. Doe, John"
    /^(?:Mrs?.)?.*\b(.*)$/ => \1 = "John"
    /^(?:Mrs?.)?.*?\b(.*)$/ => \1 = "Doe, John"
    
        2
  •  10
  •   akf    15 年前

    this link ,其中教程作者承认您问题的精神:

    乍一看,似乎 量词x?,X?和X?+do 完全一样,因为他们都 承诺匹配“X”,一次或不匹配 所有“。有一些微妙的实现 将解释的差异 在本节末尾附近。

    他们继续举例说明:

    贪婪量词被认为 “贪婪”是因为他们强迫 火柴手在里面看书,或吃东西,整个 在尝试之前输入字符串 第一场比赛。如果第一场比赛 尝试(整个输入字符串) 失败,匹配器退出输入 一个字符串起来,然后尝试 再次重复这个过程直到 找到匹配项或不再存在 字符从左移到后移。 取决于中使用的量词 表达,最后一件事 尝试匹配为1或0 字符。

    然而,不情愿的量词, 采取相反的方法:他们开始 在输入字符串的开头, 然后不情愿地吃了一个角色 找火柴的时间。最后 他们尝试的是整个输入 字符串。

    为了获得额外的荣誉,所有格的解释是:

    最后,所有格量词 总是吃掉整个输入字符串, 为一个 比赛。不像贪婪的量词, 所有格量词永不退缩, 即使这样做会允许 全面匹配才能成功。

        3
  •  3
  •   David Waters    15 年前

    一个贪婪的量词将尽可能匹配并且仍然得到匹配 一个不情愿的量词将匹配尽可能小的数量。

    例如给定字符串

    ABCDEF

    贪婪的限定符

    ab[a-z]*[a-z]将匹配abcdef

    不情愿的限定词

    AB [AZ] *?[A-Z]与ABC匹配

        4
  •  3
  •   Jorn    15 年前

    说你有一个雷吉克斯 "a\w*b" 并使用它 "abab" 贪婪匹配将匹配 “阿巴布” (它寻找一个 a ,以及 \w 尽可能,以及 b )不情愿的匹配只会匹配 "ab" (少) \w 尽可能)

        5
  •  2
  •   Brad Gilbert    15 年前

    有关于Perl如何处理这些量词的文档 perldoc perlre .

    默认情况下,量化的子模式是“贪婪的”,也就是说,它将尽可能多次匹配(给定特定的起始位置),同时仍允许模式的其余部分匹配。如果您希望它与可能的最小次数匹配,那么在量词后面加上一个“ ? “。请注意,意思并没有改变,只是“贪婪”而已:
        *?     Match 0 or more times, not greedily
        +?     Match 1 or more times, not greedily
        ??     Match 0 or 1 time, not greedily
        {n}?   Match exactly n times, not greedily
        {n,}?  Match at least n times, not greedily
        {n,m}? Match at least n but not more than m times, not greedily
    
    默认情况下,当量化的子模式不允许整个模式的其余部分匹配时,Perl将进行回溯。然而,这种行为有时是不可取的。因此,Perl也提供了“所有格”量词形式。
        *+     Match 0 or more times and give nothing back
        ++     Match 1 or more times and give nothing back
        ?+     Match 0 or 1 time and give nothing back
        {n}+   Match exactly n times and give nothing back (redundant)
        {n,}+  Match at least n times and give nothing back
        {n,m}+ Match at least n but not more than m times and give nothing back
    
    例如,
       'aaaa' =~ /a++a/
    
    永远不会匹配,因为 a++ 会吞下所有的 a 在字符串中,不会为模式的其余部分保留任何内容。这个特性对于向Perl提供不应该回溯到哪里的提示非常有用。例如,典型的“匹配双引号字符串”问题可以在以下情况下最有效地执行:
       /"(?:[^"\\]++|\\.)*+"/
    
    如我们所知,如果最终报价不匹配,回溯将不会有帮助。参见独立子表达式 (?>...) 更详细地说,所有格量词只是这个结构的句法糖分。例如,上面的例子也可以写如下:
       /"(?>(?:(?>[^"\\]+)|\\.)*)"/