在介绍非贪婪匹配前,我们先看一个简单的问题:
给定一个字符串表示的数字,判断该数字末尾0
的个数。例如:
"123000"
:3个0
"10100"
:2个0
"1001"
:0个0
可以很容易地写出该正则表达式:(\d+)(0*)
,Java代码如下:
import java.util.regex.*; public class Main { public static void main(String[] args) { Pattern pattern = Pattern.compile("(\\d+)(0*)"); Matcher matcher = pattern.matcher("1230000"); if (matcher.matches()) { System.out.println("group1=" + matcher.group(1)); // "1230000" System.out.println("group2=" + matcher.group(2)); // "" } } }
然而打印的第二个子串是空字符串""
。
实际上,我们期望分组匹配结果是:
input | \d+ | 0* |
---|---|---|
123000 | "123" | "000" |
10100 | "101" | "00" |
1001 | "1001" | "" |
但实际的分组匹配结果是这样的:
input | \d+ | 0* |
---|---|---|
123000 | "123000" | "" |
10100 | "10100" | "" |
1001 | "1001" | "" |
仔细观察上述实际匹配结果,实际上它是完全合理的,因为\d+
确实可以匹配后面任意个0
。
这是因为正则表达式默认使用贪婪匹配:任何一个规则,它总是尽可能多地向后匹配,因此,\d+
总是会把后面的0
包含进来。
要让\d+
尽量少匹配,让0*
尽量多匹配,我们就必须让\d+
使用非贪婪匹配。在规则\d+
后面加个?
即可表示非贪婪匹配。我们改写正则表达式如下: