杰瑞科技汇

Java正则find()如何匹配?

  1. 定义正则表达式:创建一个 Pattern 对象。
  2. 创建匹配器:使用 Pattern 对象和目标字符串创建一个 Matcher 对象。
  3. 执行查找:调用 Matcher 的各种 find() 方法来定位匹配的子串。

下面我们分步详细介绍。


核心类简介

  • java.util.regex.Pattern:表示一个编译后的正则表达式模式,它是不可变的,可以安全地被多个线程共享,使用 Pattern.compile() 方法来创建。
  • java.util.regex.Matcher:对输入字符串进行解释和匹配操作的引擎,它使用 Pattern 对象定义的模式来扫描字符串。
  • String 类方法String 类本身也提供了一些便捷的正则查找方法,如 matches(), replaceAll(), split() 等,但对于复杂的查找(如查找所有匹配项),Matcher 是更强大的选择。

查找的基本步骤:PatternMatcher

这是最常用、最灵活的方式,用于查找字符串中符合某个模式的子串。

示例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 类的方法,它们内部会自动处理 PatternMatcher 的创建。

示例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() 当你只需要匹配字符串开头的部分时使用。

核心要点:

  1. find() 是循环查找所有匹配项的关键。
  2. group(0) 代表整个匹配,group(n) 代表第 n 个捕获组(从1开始)。
  3. start()end() 提供了匹配项在原始字符串中的精确位置,这对于文本处理非常有用。
  4. 对于复杂的查找逻辑,优先使用 PatternMatcher 组合,而不是 String 的便捷方法。
分享:
扫描分享到社交APP
上一篇
下一篇