- 定义正则表达式:创建一个
Pattern对象。 - 创建匹配器:使用
Pattern对象和目标字符串创建一个Matcher对象。 - 执行查找:调用
Matcher的各种find()方法来定位匹配的子串。
下面我们分步详细介绍。
核心类简介
java.util.regex.Pattern:表示一个编译后的正则表达式模式,它是不可变的,可以安全地被多个线程共享,使用Pattern.compile()方法来创建。java.util.regex.Matcher:对输入字符串进行解释和匹配操作的引擎,它使用Pattern对象定义的模式来扫描字符串。String类方法:String类本身也提供了一些便捷的正则查找方法,如matches(),replaceAll(),split()等,但对于复杂的查找(如查找所有匹配项),Matcher是更强大的选择。
查找的基本步骤:Pattern 和 Matcher
这是最常用、最灵活的方式,用于查找字符串中符合某个模式的子串。
示例1:查找第一个匹配项
假设我们要从一个字符串中查找第一个出现的数字。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexFindFirst {
public static void main(String[] args) {
String text = "我的电话是 13812345678,办公室电话是 010-87654321。";
String regex = "\\d+"; // 正则表达式:匹配一个或多个数字
// 1. 编译正则表达式,创建 Pattern 对象
Pattern pattern = Pattern.compile(regex);
// 2. 创建 Matcher 对象,将 Pattern 应用到目标字符串 text 上
Matcher matcher = pattern.matcher(text);
// 3. 调用 find() 方法查找第一个匹配项
if (matcher.find()) {
// 4. 如果找到,获取匹配到的字符串
String foundText = matcher.group();
System.out.println("找到第一个匹配项: " + foundText);
System.out.println("匹配项在字符串中的起始位置: " + matcher.start());
System.out.println("匹配项在字符串中的结束位置: " + matcher.end()); // end() 是结束位置的下一个索引
} else {
System.out.println("没有找到匹配项。");
}
}
}
输出:
找到第一个匹配项: 13812345678
匹配项在字符串中的起始位置: 6
匹配项在字符串中的结束位置: 17
示例2:查找所有匹配项
如果想要找到字符串中所有符合条件的子串,就需要在一个循环中反复调用 find() 方法。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexFindAll {
public static void main(String[] args) {
String text = "订单号: ORD-2025-001, 金额: 998元, 订单号: ORD-2025-002, 金额: 1500元";
String regex = "订单号: ([A-Z]+-\\d+-\\d+)"; // 匹配订单号,并用括号捕获
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
System.out.println("所有匹配的订单号:");
// find() 方法在每次调用时,会从上一次匹配的结束位置之后开始继续查找
while (matcher.find()) {
// matcher.group() 返回整个匹配的字符串
// matcher.group(1) 返回第一个捕获组(括号内的部分)的内容
System.out.println("完整匹配: " + matcher.group());
System.out.println("捕获组1 (订单号): " + matcher.group(1));
}
}
}
输出:
所有匹配的订单号:
完整匹配: 订单号: ORD-2025-001
捕获组1 (订单号): ORD-2025-001
完整匹配: 订单号: ORD-2025-002
捕获组1 (订单号): ORD-2025-002
Matcher 的关键查找方法
| 方法 | 描述 |
|---|---|
find() |
核心查找方法,尝试查找与模式匹配的下一个子序列,如果找到,返回 true,并更新 Matcher 的状态(start(), end(), group() 等方法会指向当前匹配项)。 |
find(int start) |
从指定的索引位置开始,尝试查找下一个匹配项。 |
matches() |
尝试将整个输入字符串与模式匹配,只有当整个字符串完全符合模式时才返回 true,这与 String.matches() 类似。 |
lookingAt() |
尝试从输入字符串的开头开始,将一个子序列与模式匹配,它不像 matches() 那样要求整个字符串都匹配,但匹配必须从字符串的第一个字符开始。 |
groupCount() |
返回此匹配器模式中的捕获组数量,不包括整个匹配(即 group(0))。 |
String 类的便捷查找方法
对于一些简单的场景,可以直接使用 String 类的方法,它们内部会自动处理 Pattern 和 Matcher 的创建。
示例3:使用 String.matches() 检查整个字符串
String email = "test@example.com";
boolean isValid = email.matches("^[\\w.-]+@[\\w.-]+\\.\\w+$"); // 检查整个字符串是否是一个有效的邮箱格式
System.out.println("邮箱是否有效: " + isValid); // 输出: true
String notAnEmail = "this is not an email";
System.out.println("邮箱是否有效: " + notAnEmail.matches("^[\\w.-]+@[\\w.-]+\\.\\w+$")); // 输出: false
示例4:使用 String.replaceAll() 替换所有匹配项
String text = "Hello 123 world 456";
String replacedText = text.replaceAll("\\d", "*"); // 将所有数字替换为星号
System.out.println(replacedText); // 输出: Hello *** world ***
示例5:使用 String.split() 分割字符串
String csvData = "apple,banana,orange,grape";
String[] fruits = csvData.split(","); // 用逗号分割字符串
for (String fruit : fruits) {
System.out.println(fruit);
}
// 输出:
// apple
// banana
// orange
// grape
高级特性:捕获组
在正则表达式中,使用圆括号 可以创建捕获组,它们用于从匹配的字符串中提取特定的部分。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexCaptureGroup {
public static void main(String[] args) {
String text = "用户ID: user_123, 名字: 张三, 邮箱: zhangsan@example.com";
// 匹配 "名字: " 后面的内容,并捕获名字
String regex = "名字: (\\S+)"; // \\S+ 匹配一个或多个非空白字符
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
// matcher.group(0) 是整个匹配的字符串,即 "名字: 张三"
// matcher.group(1) 是第一个捕获组的内容,即 "张三"
System.out.println("完整匹配: " + matcher.group(0));
System.out.println("提取的名字: " + matcher.group(1));
}
}
}
输出:
完整匹配: 名字: 张三
提取的名字: 张三
总结与最佳实践
| 场景 | 推荐方法 | 说明 |
|---|---|---|
| 检查整个字符串是否符合格式 | String.matches(regex) 或 matcher.matches() |
简单直接,例如验证邮箱、手机号格式。 |
| 查找所有匹配项并处理 | Pattern.matcher(text).while(matcher.find()) |
最强大、最灵活的方式,可以获取每个匹配项的位置、内容和捕获组。 |
| 替换所有匹配项 | String.replaceAll(regex, replacement) |
简单快捷。 |
| 按模式分割字符串 | String.split(regex) |
简单快捷。 |
| 从字符串开头开始匹配 | matcher.lookingAt() |
当你只需要匹配字符串开头的部分时使用。 |
核心要点:
find()是循环查找所有匹配项的关键。group(0)代表整个匹配,group(n)代表第n个捕获组(从1开始)。start()和end()提供了匹配项在原始字符串中的精确位置,这对于文本处理非常有用。- 对于复杂的查找逻辑,优先使用
Pattern和Matcher组合,而不是String的便捷方法。
