在正则表达式的上下文中,“懒惰”和“贪婪”是什么意思?

时间:2010-02-20 06:17:35

标签: regex regex-greedy non-greedy

有人能以一种可以理解的方式解释这两个词吗?

13 个答案:

答案 0 :(得分:542)

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

<em>Hello World</em>

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

让它变得懒惰(<.+?>)会阻止这种情况发生。通过在?之后添加+,我们告诉它尽可能少地重复 ,因此它遇到的第一个>就是我们想要的地方停止匹配。

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

答案 1 :(得分:257)

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

'懒惰'表示匹配最短的字符串。

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

答案 2 :(得分:85)

+-------------------+-----------------+------------------------------+
| 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
贪婪的表达式s.*o输出: stackoverflo w
lazy reg expression s.*?o输出: stacko verflow

答案 3 :(得分:49)

贪婪意味着你的表达式将尽可能地匹配一个组,懒惰意味着它将匹配可能的最小组。对于这个字符串:

abcdefghijklmc

和这个表达:

a.*c

贪婪的匹配将匹配整个字符串,而懒惰的匹配将仅匹配第一个abc

答案 4 :(得分:12)

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

正如@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");
        }
    }
}

<小时/> 结果是:

我很开心,我想要1亿美元。这是我能得到的最多。

我懒得得这么多钱,只有100美元就足够我了

答案 5 :(得分:9)

取自www.regular-expressions.info

贪婪:贪婪量词首先尝试多次重复令牌 尽可能,并逐渐放弃匹配作为引擎回溯找到 整体比赛。

懒惰:懒惰量词首先根据需要重复令牌次数,并且 当引擎通过正则表达式回溯时,逐渐扩大匹配 找到一个整体匹配。

答案 6 :(得分:6)

来自Regular expression

  

常规的标准量词   表达是贪婪的,意思是他们   尽可能多地匹配,只给予   必要时回来匹配   正则表达式的其余部分。

     

通过使用惰性量词,   表达式尝试最小匹配   第一

答案 7 :(得分:3)

贪婪意味着它将消耗你的模式,直到它们都没有留下,它就不会再看了。

一旦遇到您要求的第一个模式,Lazy就会停止。

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

由于\s*,第一个*被归类为贪婪,并且在遇到数字后会看到尽可能多的空格,然后查找短划线字符“ - ”。由于\s*?的存在,第二个*?是懒惰的,这意味着它将看起来是第一个空格字符并停在那里。

答案 8 :(得分:2)

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

示例:

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

不是匹配直到第一次出现'&gt;',而是提取整个字符串。这是正则表达式的默认贪婪或“全部”行为。

另一方面,

懒惰匹配'尽可能少'。这可以通过在模式的末尾添加?来实现。

示例:

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

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

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

来源:Python Regex Examples

答案 9 :(得分:2)

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

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

要使正则表达式非贪婪(懒惰)在贪婪的搜索之后加上一个问号,例如 *? ?? +? 现在发生的是令牌2(+?)找到匹配,正则表达式沿着一个字符移动,然后尝试下一个令牌(\ b)而不是令牌2(+?)。所以它小心翼翼地爬行。

答案 10 :(得分:2)

贪婪的量词就像是IRS / ATO

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

国税局与此正则表达式匹配:.*

$50,000

这将匹配所有内容!

请参见此处的示例:Greedy-example

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

如果我要求退税,美国国税局突然变得不贪心,他们使用此量词:

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

第一组是非膝关节的,仅匹配$5 –因此,我会从$ 50,000输入中获得$5退款。他们不是贪婪的。他们花的时间越少越好。

请参见此处:Non-greedy-example

为什么要打扰?

如果您要匹配表达式的某些部分,则变得非常重要。有时您不想匹配所有内容。

希望这种类比可以帮助您记住!

答案 11 :(得分:1)

如果有人到达这里寻找解析时更快的速度:

  

关于正则表达式性能的一个常见误解是,懒惰的量词(也称为非贪婪,不情愿,最小或不贪婪)比它们的贪婪等价更快。通常这不是真的,但是有一个重要的限定词:在实践中,懒惰的限定词通常会更快。

摘录自Flagrant Badassery

答案 12 :(得分:-2)

尝试了解以下行为:

    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); // ""