【Java教程】Day13-05 正则表达式:贪婪与非贪婪匹配

在正则表达式中,匹配规则有两种模式:贪婪匹配和非贪婪匹配。默认情况下,正则表达式使用贪婪匹配,即尽可能多地匹配字符。有时,我们希望匹配尽可能少的字符,这时就需要使用非贪婪匹配。本文将通过具体的例子介绍贪婪与非贪婪匹配的区别,并提供如何在 Java 中实现这些匹配的教程。

1. 贪婪匹配的默认行为

首先,让我们看一个简单的示例:给定一个字符串,判断该数字末尾零的个数。比如:

  • "123000":3个0

  • "10100":2个0

  • "1001":0个0

可以通过以下正则表达式来解决:

java(\d+)(0*)

这个表达式由两部分组成:

  • (\d+):匹配一个或多个数字,表示数字部分。

  • (0*):匹配零个或多个零,表示末尾的零。

1.1 Java 代码
javaimport 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)); // ""        }    }}

1.2 输出
makefilegroup1=1230000group2=

2. 观察贪婪匹配结果

如上所示,我们期望的输出是:

  • 匹配到 "123" 和 "0000"

然而,实际结果是:

  • 匹配到 "1230000" 和 ""(空字符串)。

原因是什么呢?因为在这个正则表达式中,(\d+) 使用了贪婪匹配,它尽可能多地匹配数字,包括末尾的零。因此,0* 部分没有匹配到任何零。

3. 非贪婪匹配

要实现我们期望的结果(即将数字部分与零部分分开),我们需要让 \d+ 使用非贪婪匹配。这可以通过在 \d+ 后加上 ? 来实现,使其尽可能少地匹配字符,从而保留末尾的零。

3.1 修改后的代码
javaimport 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)); // "123"            System.out.println("group2=" + matcher.group(2)); // "0000"        }    }}

3.2 输出
makefilegroup1=123group2=0000

现在,输出符合预期,group1 为 "123"group2 为 "0000",实现了将数字和零分开。

4. 进一步理解非贪婪匹配

非贪婪匹配不仅限于处理零个或多个字符,还可以应用于其它场景。来看另一个例子:

正则表达式:(\d??)(9*)

在这个例子中:

  • \d? 表示匹配零个或一个数字。

  • 9* 表示匹配零个或多个数字 9。

由于 \d? 后面跟了一个 ?,它会尽可能少地匹配字符,因此,当输入字符串是 "9999" 时,(\d??) 会首先匹配到零个 9(尽可能少匹配),然后 9* 会匹配到剩余的 "9999"

4.1 示例代码
javaimport java.util.regex.*;public class Main {    public static void main(String[] args) {        Pattern pattern = Pattern.compile("(\\d??)(9*)");        Matcher matcher = pattern.matcher("9999");        if (matcher.matches()) {            System.out.println("group1=" + matcher.group(1)); // ""            System.out.println("group2=" + matcher.group(2)); // "9999"        }    }}

4.2 输出
makefilegroup1=group2=9999

可以看到,group1 匹配了一个空字符串,因为 \d? 非贪婪地匹配了零个数字,group2 则匹配了所有的数字 "9999"

5. 小结

在正则表达式中,默认的匹配模式是贪婪匹配,即尽可能多地匹配字符。如果希望尽量少地匹配字符,可以使用非贪婪匹配。实现非贪婪匹配的方法是在相关模式后加上 ?,例如 \d+? 表示尽量少地匹配数字。

6. 关键点

  • 贪婪匹配:正则表达式会尽量多地匹配字符,直到满足整个表达式。

  • 非贪婪匹配:通过在匹配模式后加上 ? 来实现,使其尽量少地匹配字符。

  • ? 的作用:在 * 和 + 后添加 ?,使其变为非贪婪模式。例如,\d+? 表示尽量少地匹配数字。

通过理解并掌握非贪婪匹配,你可以在 Java 中更灵活地使用正则表达式,处理复杂的字符串匹配和提取任务。

你可能感兴趣的:(Java教程,java,正则表达式,开发语言)