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

What do 'lazy' and 'greedy' mean in the context of regular expressions?

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


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

1
Hello World

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

让它变懒(<.+?>会阻止这一点。在+之后加上?,我们告诉它尽量重复几次,所以它遇到的第一个>就是我们要停止匹配的地方。

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


"greedy"表示匹配尽可能长的字符串。

"lazy"表示匹配尽可能短的字符串。

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


1
2
3
4
5
6
7
8
9
10
+-------------------+-----------------+------------------------------+
| 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  |
+-------------------+-----------------+------------------------------+

Add a ? to a quantifier to make it ungreedy i.e lazy.

例子:测试字符串:stackoverflow贪婪注册表表达式:s.*o输出:stackoverflowLazy Reg表达式:s.*?o输出:stackOverflow


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

1
abcdefghijklmc

这个表达式:

1
a.*c

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


据我所知,大多数regex引擎在默认情况下都是贪婪的。在量词末尾添加问号将启用惰性匹配。

正如评论中提到的那样。

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

请参阅下面的示例,了解什么是贪婪的,什么是懒惰的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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");
        }
    }
}

结果是:

我是格蕾迪,我要100000000美元。这是我能得到的最多的。

我太懒了,拿不到这么多钱,只有100美元就够了


摘自www.regular-expressions.info

贪婪:贪婪的量词首先尝试重复符号多次尽可能,并逐渐放弃匹配作为引擎的回溯来查找整体匹配。

惰性:惰性量词首先根据需要重复标记几次,并且随着引擎在regex中的后退,匹配逐渐扩展到找到一个整体匹配。


从正则表达式

The standard quantifiers in regular
expressions are greedy, meaning they
match as much as they can, only giving
back as necessary to match the
remainder of the regex.

By using a lazy quantifier, the
expression tries the minimal match
first.


贪婪意味着它将消耗你的模式,直到没有一个模式被保留下来,并且它不能再看下去。

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

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

由于*,第一个\s*被归类为贪婪,遇到数字后将尽可能多地查找空格,然后查找破折号"-"。当第二个\s*?因为*?的存在而懒惰的时候,这意味着它会看到第一个空白字符,就停在那里。


最佳shown by example。字符串。正则表达式 192.168.1.1和贪婪的B + B"的。你可能会认为这会给你真爱第一octet but is the Whole matches对字符串。为什么!!!!!!!!!!!!!!!因为茶是贪婪和贪婪。+匹配每个字符是192.168.1.1 matches中直到它为the end of the字符串。This is the important位!!!!!!!!!!!!!!!现在它开始的时间,直到一个字符backtrack(EN for the 3rd在比赛里找到自己的令牌()。P></

if the text文件和字符串到4GB was at the start 192.168.1.1,你可能会easily see how this backtracking会安问题的原因。P></

不要让贪婪的正则表达式(懒惰)在把贪婪的搜索你的问题后e.g马克*???+?2什么是发生在现在的令牌(+?)正则表达式在比赛里找到自己的动作,然后在tries the next character令牌令牌("b)比2(+?)我知道creeps gingerly。恩在。P></


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

例子:

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

它提取了整个字符串,而不是匹配到第一次出现">"。这是regex的默认贪婪或"全力以赴"行为。

另一方面,懒惰的匹配"尽可能少"。这可以通过在模式末尾添加一个?来实现。

例子:

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

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

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

来源:python regex示例


尝试理解以下行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    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); //""