`Greedy`和`Reluctant`正则表达式量词有什么区别?

时间:2009-07-16 17:43:29

标签: java regex

来自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进行编码,但我听说这个概念对于大多数现代正则表达式实现都是一样的。

5 个答案:

答案 0 :(得分:38)

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

示例:

"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"

答案 1 :(得分:10)

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

  乍一看,它可能会出现   量词X?,X ??和X?+做   完全相同的事情,因为他们都是   承诺匹配“X,一次或不一次   所有“。有微妙的实施   差异将被解释   接近本节结尾。

他们继续汇总实例并提供解释:

  

考虑贪婪量词   “贪婪”,因为他们强迫   匹配器读入或吃掉整个   在尝试之前输入字符串   第一场比赛。如果第一场比赛   尝试(整个输入字符串)   失败,匹配器退出输入   字符串由一个字符和尝试   再次,重复这个过程,直到a   匹配被找到或没有更多   从左到右的字符。   取决于使用的量词   表达,它将是最后一件事   尝试匹配是1还是0   字符。

     

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

还有额外的功劳,占有欲的解释:

  

最后,占有量词   总是吃整个输入字符串,   尝试一次(并且只尝试一次)   比赛。与贪婪的量词不同,   占有量词永远不会退缩,   即使这样做也会允许   总体比赛成功。

答案 2 :(得分:3)

贪婪的量词将尽可能匹配并仍然匹配 不情愿的量词将匹配可能的最小量。

例如给定字符串

ABCDEF

贪婪的限定词

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

不情愿的限定词

ab [a-z] *?[a-z]匹配abc

答案 3 :(得分:3)

说你有正则表达式"a\w*b",并在"abab"上使用它 贪婪匹配将匹配"abab"(它会查找a,尽可能多地出现\w,而b)和不情愿的匹配仅匹配"ab" }(尽可能少\w

答案 4 :(得分:2)

有关于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提示非常有用。例如,当写为:时,可以最有效地执行典型的“匹配双引号字符串”问题:
   /"(?:[^"\\]++|\\.)*+"/
我们知道,如果最终报价不匹配,回溯将无济于事。有关详细信息,请参阅独立子表达式(?>...);占有量词只是该构造的语法糖。例如,上面的例子也可以写成如下:
   /"(?>(?:(?>[^"\\]+)|\\.)*)"/