Java MatchResult.groupCount 方法
上次修改时间:2025 年 4 月 20 日
MatchResult.groupCount 方法返回正则表达式模式中捕获组的数量。 它是 java.util.regex.MatchResult 接口的一部分。 此方法对于处理使用组的复杂正则表达式模式至关重要。
捕获组是正则表达式模式中用括号括起来的部分。 它们允许您提取匹配文本的特定部分。 groupCount 方法有助于确定模式中存在多少个这样的组。
MatchResult.groupCount 概述
groupCount 方法返回一个整数,表示模式中捕获组的数量。 此计数不包括特殊组 0,它始终表示整个匹配项。 该方法在 Matcher 对象和其他实现 MatchResult 的类上可用。
理解组计数在处理匹配项时至关重要,因为它有助于您了解可以访问多少个组。 可以使用索引从 1 到 groupCount() 的 group(int) 方法检索每个组。
基本 groupCount 示例
此示例演示了 groupCount 的基本用法,其中包含一个包含两个捕获组的简单模式。 我们将看到如何访问组计数和单个组。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class BasicGroupCount {
public static void main(String[] args) {
String input = "John Doe, age 30";
String regex = "(\\w+) (\\w+), age (\\d+)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Total groups: " + matcher.groupCount());
System.out.println("Full match: " + matcher.group(0));
System.out.println("First name: " + matcher.group(1));
System.out.println("Last name: " + matcher.group(2));
System.out.println("Age: " + matcher.group(3));
}
}
}
在此示例中,我们创建一个包含三个捕获组的模式。 groupCount 方法返回 3,与我们的三个带括号的组匹配。 然后,我们使用其索引 (1-3) 访问每个组,并使用索引 0 访问完整匹配项。
输出显示组 0 包含整个匹配项,而组 1-3 包含捕获的子字符串。 这演示了 groupCount 如何帮助浏览捕获的组。
groupCount 与嵌套组
此示例显示了 groupCount 如何与嵌套捕获组一起使用。 嵌套组会使模式更加复杂,但 groupCount 仍然可以准确地报告总数。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NestedGroups {
public static void main(String[] args) {
String input = "2023-05-15";
String regex = "((\\d{4})-(\\d{2})-(\\d{2}))";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Total groups: " + matcher.groupCount());
System.out.println("Full match: " + matcher.group(0));
System.out.println("Outer group: " + matcher.group(1));
System.out.println("Year: " + matcher.group(2));
System.out.println("Month: " + matcher.group(3));
System.out.println("Day: " + matcher.group(4));
}
}
}
这里我们有一个带有嵌套组的日期模式。 外部组捕获整个日期,而内部组分别捕获年、月和日。 groupCount 返回 4,计算所有捕获组。
请注意,组 1 包含完整日期(与组 0 相同),而组 2-4 包含各个组件。 这表明嵌套组是如何从左到右按顺序计数的。
groupCount 与非捕获组
此示例演示了非捕获组(使用 (?:...))如何影响组计数。 非捕获组对于应用量词而不创建捕获组非常有用。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NonCapturingGroups {
public static void main(String[] args) {
String input = "color or colour";
String regex = "col(o?:u)r";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
System.out.println("\nMatch: " + matcher.group(0));
System.out.println("Total groups: " + matcher.groupCount());
System.out.println("Group 1: " + matcher.group(1));
}
}
}
在此模式中,我们有一个捕获组和一个非捕获组。 groupCount 返回 1,因为仅计算显式捕获组。 非捕获组不会增加计数。
输出显示,尽管模式中有两个带括号的表达式,但只有一个被计数并通过 group(1) 访问。 这演示了在不需要捕获时如何优化模式。
groupCount 与命名组
Java 支持使用 (?<name>...) 语法命名捕获组。 此示例显示了命名组如何影响 groupCount 以及如何访问它们。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NamedGroups {
public static void main(String[] args) {
String input = "Product: Laptop, Price: $999.99";
String regex = "Product: (?<product>\\w+), Price: \\$(?<price>\\d+\\.\\d{2})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Total groups: " + matcher.groupCount());
System.out.println("Full match: " + matcher.group(0));
System.out.println("Product (by name): " + matcher.group("product"));
System.out.println("Product (by index): " + matcher.group(1));
System.out.println("Price (by name): " + matcher.group("price"));
System.out.println("Price (by index): " + matcher.group(2));
}
}
}
此示例使用两个命名组:“product”和“price”。 groupCount 返回 2,因为命名组仍然像往常一样计数。 可以通过名称或数字索引访问它们。
命名组使模式更具可读性和可维护性,尤其是在复杂模式下。 无论组是否命名,groupCount 方法的工作方式都相同。
groupCount 与零组
此示例显示了当模式没有捕获组时 groupCount 的行为。 它有助于理解组计数的基线情况。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ZeroGroups {
public static void main(String[] args) {
String input = "Simple text matching";
String regex = "[A-Za-z ]+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Total groups: " + matcher.groupCount());
System.out.println("Full match: " + matcher.group(0));
// Attempting to access group 1 would throw IndexOutOfBoundsException
try {
System.out.println("Group 1: " + matcher.group(1));
} catch (IndexOutOfBoundsException e) {
System.out.println("Cannot access group 1: " + e.getMessage());
}
}
}
}
这里我们有一个没有捕获组的模式。 groupCount 方法返回 0,表示除了组 0(完整匹配)之外,没有其他组可以访问。 尝试访问组 1 会引发异常。
这表明 groupCount 准确地反映了模式何时没有捕获组。 在通过索引访问组之前,检查此项始终是安全的。
groupCount 与交替
此示例探讨了交替(使用 | 运算符)如何影响组计数。 我们将看到交替的不同分支如何具有不同数量的组。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AlternationGroups {
public static void main(String[] args) {
String input1 = "Date: 2023-05-15";
String input2 = "Timestamp: 202305151200";
String regex = "(Date: (\\d{4}-\\d{2}-\\d{2}))|(Timestamp: (\\d{12}))";
Pattern pattern = Pattern.compile(regex);
// Test first pattern branch
Matcher matcher1 = pattern.matcher(input1);
if (matcher1.find()) {
System.out.println("Input1 groups: " + matcher1.groupCount());
System.out.println("Full match: " + matcher1.group(0));
System.out.println("Date group: " + matcher1.group(1));
System.out.println("Date value: " + matcher1.group(2));
}
// Test second pattern branch
Matcher matcher2 = pattern.matcher(input2);
if (matcher2.find()) {
System.out.println("\nInput2 groups: " + matcher2.groupCount());
System.out.println("Full match: " + matcher2.group(0));
System.out.println("Timestamp group: " + matcher2.group(3));
System.out.println("Timestamp value: " + matcher2.group(4));
}
}
}
此模式具有交替,每个分支中的组数不同。 groupCount 返回 4,表示整个模式中捕获组的总数,无论哪个分支匹配。
当第一个分支匹配时,组 1 和 2 包含值,而组 3 和 4 为 null。 相反,当第二个分支匹配时,组 3 和 4 包含值。 这显示了 groupCount 如何报告最大可能的组数。
groupCount 在替换操作中
最后一个示例演示了在字符串替换操作的上下文中使用 groupCount。 我们将看到组计数如何影响替换模式。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ReplacementGroups {
public static void main(String[] args) {
String input = "Name: John Doe, Phone: (123) 456-7890";
String regex = "Name: (\\w+) (\\w+), Phone: \\((\\d{3})\\) (\\d{3})-(\\d{4})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Total groups: " + matcher.groupCount());
// Simple replacement using group references
String result1 = matcher.replaceAll("Contact: $1 $2, Phone: ($3) $4-$5");
System.out.println("\nReplacement 1: " + result1);
// More complex replacement using group count
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= matcher.groupCount(); i++) {
sb.append("Group ").append(i).append(": [")
.append(matcher.group(i)).append("] ");
}
String result2 = matcher.replaceAll(sb.toString());
System.out.println("Replacement 2: " + result2);
}
}
}
此示例显示了使用组引用的两个替换操作。 groupCount 帮助我们了解可以在替换中引用多少个组。 第一个替换使用固定的组引用,而第二个替换基于组计数动态构建替换。
输出演示了替换字符串中的组引用($1、$2 等)如何对应于捕获的组。 了解组计数对于创建正确的替换模式至关重要。
来源
在本文中,我们通过各种示例彻底探讨了 MatchResult.groupCount 方法。 理解组计数对于 Java 中有效的正则表达式处理至关重要。
作者
列出所有Java教程。