ZetCode

Java MatchResult.group 方法

上次修改时间:2025 年 4 月 20 日

MatchResult.group 方法是 Java 正则表达式 API 的一部分。它返回匹配期间由捕获组捕获的输入子序列。MatchResult 是 Matcher 实现的接口。

捕获组从左到右编号,从 1 开始。组 0 始终指整个匹配项。group 方法有多个重载,可以通过数字或名称访问组。

MatchResult.group 概述

MatchResult 接口提供了查询匹配操作结果的方法。group 方法是访问捕获组的主要方式。它有三种变体。

group 返回整个匹配项(与组 0 相同)。group(int group) 返回按编号指定的组。group(String name) 返回命名组(Java 7+)。

Basic group() 用法

group 最简单的形式返回整个匹配项。这相当于调用 group(0)。当您不需要访问特定的捕获组时,它非常有用。

BasicGroupExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BasicGroupExample {

    public static void main(String[] args) {
        String input = "The quick brown fox jumps over the lazy dog";
        String regex = "quick.*fox";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Full match: " + matcher.group());
            System.out.println("Same as group 0: " + matcher.group(0));
        }
    }
}

在此示例中,我们在输入字符串中搜索模式“quick.*fox”。当我们找到匹配项时,我们使用 groupgroup(0) 打印整个匹配的子序列。

两个调用都返回相同的结果:“quick brown fox”。这表明 group 是访问完整匹配项的便捷简写。

访问编号组

编号的捕获组允许您提取匹配项的特定部分。组从左到右根据它们的左括号进行编号。组 0 始终是整个匹配项。

NumberedGroupsExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NumberedGroupsExample {

    public static void main(String[] args) {
        String input = "John Doe, age 30, email: john.doe@example.com";
        String regex = "(\\w+ \\w+), age (\\d+), email: (\\S+)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            System.out.println("Name: " + matcher.group(1));
            System.out.println("Age: " + matcher.group(2));
            System.out.println("Email: " + matcher.group(3));
        }
    }
}

此示例演示如何访问编号的捕获组。正则表达式模式包含三个用括号括起来的捕获组。

组 1 捕获名称,组 2 捕获年龄,组 3 捕获电子邮件。我们使用带有相应组号的 group(int) 访问每个组。

命名捕获组

Java 7 引入了命名捕获组,这使正则表达式模式更具可读性。可以使用 (?<name>...) 语法命名组。可以通过名称访问命名组。

NamedGroupsExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NamedGroupsExample {

    public static void main(String[] args) {
        String input = "Date: 2023-04-20, Time: 14:30";
        String regex = "Date: (?<date>\\d{4}-\\d{2}-\\d{2}), Time: (?<time>\\d{2}:\\d{2})";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Full match: " + matcher.group());
            System.out.println("Date: " + matcher.group("date"));
            System.out.println("Time: " + matcher.group("time"));
            
            // Named groups also have numbers
            System.out.println("Date (group 1): " + matcher.group(1));
            System.out.println("Time (group 2): " + matcher.group(2));
        }
    }
}

此示例显示了如何定义和访问命名捕获组。正则表达式包含两个命名组:“date”和“time”。

我们使用 group(String name) 访问这些组。请注意,命名组也具有相应的编号,因此也可以通过编号访问它们。这为您提供了引用捕获组的灵活性。

具有组的多个匹配项

在字符串中处理多个匹配项时,每个匹配项都维护自己的组信息。find 方法前进到下一个匹配项,并相应地更新组信息。

MultipleMatchesExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MultipleMatchesExample {

    public static void main(String[] args) {
        String input = "Product: Laptop, Price: $999.99; Product: Mouse, Price: $49.99";
        String regex = "Product: (?<product>\\w+), Price: \\$(?<price>\\d+\\.\\d{2})";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        while (matcher.find()) {
            System.out.println("Product: " + matcher.group("product"));
            System.out.println("Price: " + matcher.group("price"));
            System.out.println("---");
        }
    }
}

此示例处理字符串中的多个产品条目。对于 find 找到的每个匹配项,我们可以访问当前匹配项的组。

while 循环持续进行,直到处理完所有匹配项。每次迭代都可以访问该特定匹配项的组。这对于从文本中提取结构化数据非常有用。

处理可选组

正则表达式模式中的某些捕获组可能是可选的。当可选组不参与匹配时,group 会为该组返回 null。在使用可选组时,始终检查 null。

OptionalGroupsExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OptionalGroupsExample {

    public static void main(String[] args) {
        String[] inputs = {
            "Error: 404 - Not Found",
            "Error: 500",
            "Error: 403 - Forbidden"
        };
        
        String regex = "Error: (\\d+)(?: - (.*))?";
        Pattern pattern = Pattern.compile(regex);
        
        for (String input : inputs) {
            Matcher matcher = pattern.matcher(input);
            if (matcher.find()) {
                System.out.println("Error code: " + matcher.group(1));
                
                String description = matcher.group(2);
                if (description != null) {
                    System.out.println("Description: " + description);
                } else {
                    System.out.println("No description provided");
                }
                System.out.println("---");
            }
        }
    }
}

此示例演示了处理可选组。正则表达式模式使用 ? 量词使错误描述成为可选的。

对于没有描述的输入,group(2) 返回 null。我们在使用组值之前检查 null。这可以防止在使用模式的可选部分时出现 NullPointerException。

组计数和验证

在访问组之前,最好验证它们的存在。groupCount 方法返回模式中捕获组的数量。请记住,组 0 不包含在此计数中。

GroupCountExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GroupCountExample {

    public static void main(String[] args) {
        String input = "RGB: (255, 128, 64)";
        String regex = "RGB: \\((\\d+), (\\d+), (\\d+)\\)";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        System.out.println("Total groups (excluding group 0): " + 
            matcher.groupCount());
            
        if (matcher.find()) {
            for (int i = 0; i <=  matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }
    }
}

此示例显示了如何使用 groupCount 来确定有多少个捕获组可用。该模式具有三个用于 RGB 分量的显式组。

我们循环访问所有组(包括组 0)以显示它们的值。了解组计数有助于编写需要处理可变数量组的代码。

高级组提取

对于具有嵌套组的复杂模式,了解组编号至关重要。组根据其左括号的顺序编号,包括嵌套组。

NestedGroupsExample.java
package com.zetcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class NestedGroupsExample {

    public static void main(String[] args) {
        String input = "Coordinates: (40.7128° N, 74.0060° W)";
        String regex = "(\\(([\\d.]+)° ([NS]), ([\\d.]+)° ([EW])\\))";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        if (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            System.out.println("All parentheses: " + matcher.group(1));
            System.out.println("Latitude value: " + matcher.group(2));
            System.out.println("Latitude direction: " + matcher.group(3));
            System.out.println("Longitude value: " + matcher.group(4));
            System.out.println("Longitude direction: " + matcher.group(5));
        }
    }
}

此示例演示了具有嵌套捕获组的组编号。正则表达式包含多个嵌套级别,用于解析地理坐标。

组 1 捕获外括号中的所有内容。组 2-5 捕获单个组件。在处理复杂模式时,了解此编号至关重要。

来源

Java MatchResult 文档

在本文中,我们介绍了 MatchResult.group 方法的基本方面。理解捕获组对于在 Java 中使用正则表达式进行有效的文本处理至关重要。

作者

我叫 Jan Bodnar,是一位拥有多年经验的专注程序员。我于 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程