Java Matcher 类
上次修改时间:2025 年 4 月 20 日
java.util.regex.Matcher 类用于使用模式对字符序列执行匹配操作。 它根据输入文本解释编译的正则表达式模式以查找匹配项。 Matcher 对象不是线程安全的。
Matcher 提供了执行各种匹配操作、检查匹配结果和修改输入文本的方法。 它与 Pattern 类协同工作,以在 Java 应用程序中提供完整的正则表达式功能。
Matcher 类概述
Matcher 是通过使用输入序列调用 Pattern.matcher 来创建的。 它维护有关当前匹配位置的状态,并提供查询和操作匹配项的方法。 该类支持简单和复杂的匹配场景。
关键方法包括 matches、find、group 以及各种替换方法。 Matcher 还支持命名捕获组和区域限制以进行部分匹配。
基本匹配操作
Matcher 类提供了三种基本的匹配方法:matches、lookingAt 和 find。 每种方法在模式匹配操作中都具有不同的用途。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherBasic {
public static void main(String[] args) {
String input = "The quick brown fox jumps over the lazy dog";
Pattern pattern = Pattern.compile("quick.*fox");
Matcher matcher = pattern.matcher(input);
// matches() - entire input must match
System.out.println("matches(): " + matcher.matches());
// lookingAt() - input must match from beginning
System.out.println("lookingAt(): " + matcher.lookingAt());
// find() - match anywhere in input
System.out.println("find(): " + matcher.find());
// Reset matcher to start from beginning
matcher.reset();
// Find all matches
System.out.println("\nAll matches:");
while (matcher.find()) {
System.out.println("Found at: " + matcher.start() + "-" + matcher.end());
}
}
}
此示例演示了三种基本的匹配方法。 matches 检查整个输入是否与模式匹配。 lookingAt 检查输入是否以模式开头。 find 在输入中的任何位置搜索该模式。
该示例还显示了如何使用 start 和 end 来获取匹配位置。 reset 将 matcher 重新定位到输入的开头以进行重复搜索。
组捕获
Matcher 支持捕获由正则表达式模式中的括号定义的组。 组允许提取匹配文本的特定部分。 组 0 表示整个匹配,而组 1+ 表示捕获的子模式。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherGroups {
public static void main(String[] args) {
String input = "John Doe, age 30, email: john.doe@example.com";
Pattern pattern = Pattern.compile(
"(\\w+ \\w+), age (\\d+), email: (\\S+@\\S+)");
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));
System.out.println("\nGroup count: " + matcher.groupCount());
}
}
}
此示例使用捕获组从输入字符串中提取姓名、年龄和电子邮件。 该模式定义了三个用括号括起来的组。 成功匹配后,可以通过其索引检索每个组的内容。
groupCount 返回模式中捕获组的数量(不包括组 0)。 组从左到右根据其左括号进行编号。
命名捕获组
Java 7 引入了使用 (?<name>...) 语法的命名捕获组。 命名组使模式更具可读性,并且匹配更容易处理。 可以使用组名而不是数字索引。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherNamedGroups {
public static void main(String[] args) {
String input = "Date: 2023-05-15, Time: 14:30";
Pattern pattern = Pattern.compile(
"Date: (?<date>\\d{4}-\\d{2}-\\d{2}), Time: (?<time>\\d{2}:\\d{2})");
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Date: " + matcher.group("date"));
System.out.println("Time: " + matcher.group("time"));
// Still accessible by index
System.out.println("\nGroup 1: " + matcher.group(1));
System.out.println("Group 2: " + matcher.group(2));
}
}
}
此示例演示了命名组捕获。 该模式定义了两个命名组:“date”和“time”。 与数字组引用相比,这些名称使代码更具可读性和可维护性。
命名组仍然可以通过其数字索引访问,从而保持向后兼容性。 组命名语法有助于记录正则表达式本身内的模式结构。
文本替换
Matcher 通过 replaceAll 和 replaceFirst 方法提供强大的文本替换功能。 这些方法允许使用文字字符串或组引用来转换匹配的文本。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherReplace {
public static void main(String[] args) {
String input = "User: john_doe, Email: john@example.com";
Pattern pattern = Pattern.compile("(\\w+)@(\\w+\\.\\w+)");
Matcher matcher = pattern.matcher(input);
// Replace first match
String firstReplaced = matcher.replaceFirst("EMAIL_REDACTED");
System.out.println("First replaced: " + firstReplaced);
// Replace all matches
String allReplaced = matcher.replaceAll("$1@DOMAIN.REDACTED");
System.out.println("All replaced: " + allReplaced);
// Append replacement using appendReplacement/appendTail
matcher.reset();
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1) + "@NEW.DOMAIN");
}
matcher.appendTail(sb);
System.out.println("Custom replacement: " + sb.toString());
}
}
此示例显示了三种替换技术。 replaceFirst 仅替换第一个匹配项,而 replaceAll 替换所有匹配项。 美元符号表示法 ($1) 引用捕获的组。
对于更复杂的替换,appendReplacement 和 appendTail 提供细粒度控制。 这些方法允许单独处理匹配项,同时以增量方式构建结果。
区域操作
Matcher 支持区域限制,以将匹配限制为输入的一部分。 region 方法定义了匹配操作的边界,而 useAnchoringBounds 和 useTransparentBounds 控制边界行为。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherRegion {
public static void main(String[] args) {
String input = "Start: 123 Middle: 456 End: 789";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(input);
// Set region from index 10 to 25
matcher.region(10, 25);
System.out.println("Region matches:");
while (matcher.find()) {
System.out.println("Found: " + matcher.group() +
" at " + matcher.start());
}
// Check anchoring bounds behavior
matcher.region(15, 25);
matcher.useAnchoringBounds(false);
System.out.println("\nWithout anchoring bounds:");
System.out.println("^ matches: " + matcher.hitEnd());
}
}
此示例演示了区域操作。 第一部分将匹配限制为输入的字符 10-25,有效地跳过“Start: 123”和“End: 789”。 仅找到指定区域内的数字。
第二部分显示了锚定边界如何影响模式匹配。 禁用后,^ 和 $ 锚点将不会在区域边界处匹配。 hitEnd 指示匹配是否到达输入区域的末尾。
使用标志进行模式匹配
Matcher 从其 Pattern 对象继承模式标志,但可以覆盖某些行为。 useCaseInsensitive 方法启用不区分大小写的匹配,而无需重新创建 matcher。
package com.zetcode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherFlags {
public static void main(String[] args) {
String input = "The Quick BROWN fox JUMPS over the lazy DOG";
Pattern pattern = Pattern.compile("\\b[a-z]+\\b");
Matcher matcher = pattern.matcher(input);
System.out.println("Default matching (case sensitive):");
while (matcher.find()) {
System.out.println(matcher.group());
}
// Enable case-insensitive matching
matcher.reset();
matcher.useCaseInsensitive(true);
System.out.println("\nCase-insensitive matching:");
while (matcher.find()) {
System.out.println(matcher.group());
}
}
}
此示例显示了如何在创建 matcher 后修改匹配行为。 第一次传递使用区分大小写的匹配,仅查找小写单词。 启用不区分大小写的模式后,所有单词都将被匹配,而不管大小写如何。
reset 在将 matcher 重用于新标志之前清除其状态。 当只需要更改标志时,此方法比创建新的 matcher 更有效。
来源
本教程介绍了 Java Matcher 类的重要方法和功能。 掌握这些概念对于在 Java 应用程序中使用正则表达式进行有效的文本处理至关重要。
作者
列出所有Java教程。