Java 正则表达式 - 添加括号使其变得贪婪?

Java regexp - adding parenthesis makes it greedy?

public void name() throws Exception {
        Pattern p = Pattern.compile("\d{1,2}?");
        String input = "09";
        Matcher m = p.matcher(input);
        StringBuffer sb = new StringBuffer();
        while(m.find()) {
            System.out.println("match = "+m.group());
        }
    }

上述方法的输出是:

match = 0
match = 9

现在,我只是在正则表达式中添加括号:

public void name() throws Exception {
        Pattern p = Pattern.compile("(\d{1,2})?");
        String input = "09";
        Matcher m = p.matcher(input);
        StringBuffer sb = new StringBuffer();
        while(m.find()) {
            System.out.println("match = "+m.group());
        }
    }

输出变为:

match = 09
match = 
  1. 这里为什么括号要匹配贪心
  2. [编辑,稍后补充]为什么第一种情况匹配不到空字符串?

为了使量词(?*+{n,m})不情愿(非贪婪或惰性),它必须跟在后面通过 ?。所以模式\d{1,2}?勉强

另一方面,(\d{1,2})?两层贪心量词组成:

  1. 一个组 (\d{1,2}) 包含一个带有贪婪量词的模式 {1,2},
  2. 后跟 ? 贪婪量词。

因此,(\d{1,2})? 是贪心的,因为 ? 不会 立即 跟随量词(中间有一个括号关闭组),因此它充当不情愿的正则表达式的元字符。

参考this page about quantifiers

让我们从简单的量词正则表达式开始:

\d{1,2}

这本质上是贪婪,将匹配min(即1)和max(即2).

所以对于我们的输入 09,它只会匹配 09.

现在让我们惰性使用:

\d{1,2}?

这将使尽可能少次。因此,对于相同的输入,它将第一次匹配 0,第二次匹配 9(因为您使用的是 while 循环)。

现在第 3 个案例:

(\d{1,2})?

它匹配 0 次或 1 次出现的贪婪 \d{1,2},这意味着匹配 \d{1,2} 或什么都不匹配。

因此对于相同的输入,它将匹配:

  1. 09
  2. 空字符串

这是因为我们通过将 ? 放在 (...)

之外来使整个组可选