678

这两个术语是什么意思?

4

12 回答 12

806

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

<em>Hello World</em>

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

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

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

于 2010-02-20T06:22:32.030 回答
388

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

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

例如,贪婪h.+l匹配'hell'in'hello'但惰性h.+?l匹配'hel'

于 2010-02-20T06:19:41.160 回答
198
贪心量词 惰性量词 描述
* *? 星量词:0或更多
+ +? 加量词:1个或更多
? ?? 可选量词:0 或 1
{n} {n}? 量词:正好 n
{n,} {n,}? 量词:n 或更多
{n,m} {n,m}? 量词:在 n 和 m 之间

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

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

于 2016-01-15T07:26:36.037 回答
68

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

abcdefghijklmc

这个表达式:

a.*c

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

于 2010-02-20T06:19:18.480 回答
23

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

正如@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
于 2016-11-09T16:39:06.257 回答
18

取自www.regular-expressions.info

贪婪:贪婪量词首先尝试尽可能多地重复令牌,并随着引擎回溯以找到整体匹配而逐渐放弃匹配。

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

于 2014-10-19T08:34:34.073 回答
10

正则表达式

正则表达式中的标准量词是贪婪的,这意味着它们尽可能匹配,只在必要时返回以匹配正则表达式的其余部分。

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

于 2010-02-20T06:21:22.360 回答
6

贪婪的量词就像美国国税局

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

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

$50,000

再见银行余额。

请参阅此处的示例:贪婪示例

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

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

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

第一组是非需要的,只匹配$5- 所以我得到了$550,000 美元输入的退款。他们尽可能少地服用。

请参见此处:非贪婪示例

为什么我们需要贪婪与非贪婪?

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

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

于 2020-01-28T05:23:16.370 回答
4

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

例子:

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

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

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

例子:

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

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

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

来源:Python 正则表达式示例

于 2018-01-21T05:35:59.513 回答
4

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

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

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

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

于 2018-02-06T15:41:32.830 回答
4

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

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

要使正则表达式不贪婪(懒惰),请在贪婪搜索之后放置一个问号,例如

*?
??
+?

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

于 2018-03-12T10:54:44.627 回答
-3

尝试理解以下行为:

    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); // ""
于 2016-10-30T06:31:14.943 回答