杰瑞科技汇

Java正则matcher如何高效匹配与使用?

  • Pattern (模式):就像一个编译好的“模板”或“规则”,它是一个 final 类,代表一个经过编译的正则表达式,你不会直接创建 Pattern 实例,而是通过 Pattern.compile() 静态方法。
  • Matcher (匹配器):像一个“引擎”或“扫描仪”,它使用 Pattern 这个模板,在一个具体的输入字符串上进行查找、匹配和替换操作。

一个 Pattern 对象可以对应多个 Matcher 对象,每个 Matcher 对象用于处理不同的输入字符串。


核心工作流程

使用 Matcher 的标准三步流程:

  1. 定义正则表达式:写一个符合正则语法的字符串。
  2. 编译 Pattern:使用 Pattern.compile() 将你的正则表达式字符串编译成一个 Pattern 对象,这一步是高效的,如果要对多个字符串使用同一个正则表达式,只编译一次即可。
  3. 创建 Matcher:使用 pattern.matcher(input) 方法,将你的输入字符串和 Pattern 关联起来,创建一个 Matcher 实例。
  4. 执行匹配操作:调用 Matcher 的各种方法来执行查找、匹配等操作。

Matcher 的核心方法详解

Matcher 提供了丰富的方法,下面分类介绍最常用的几种。

查找与匹配方法

这些方法用于判断输入字符串中是否存在符合模式的子串。

方法 描述 示例
boolean find() 最常用,尝试在输入字符串中查找下一个匹配的子串,找到返回 true,找不到返回 false,可以多次调用,从上次匹配位置的下一个位置开始继续查找。 查找字符串中所有出现的 "cat"
boolean find(int start) 从指定的索引位置 start 开始,尝试查找下一个匹配的子串。 从第 5 个字符开始查找 "cat"
boolean matches() 尝试将整个输入字符串与模式匹配,只有当整个字符串完全符合模式时才返回 true 验证一个字符串是否是一个合法的邮箱地址
boolean lookingAt() 尝试从输入字符串的开头开始匹配模式,与 matches() 类似,但它不要求整个字符串都匹配,只要开头部分匹配即可。 检查字符串是否以 "http://" 开头

获取匹配结果的方法

find()matches() 返回 true 后,可以使用这些方法获取匹配到的内容。

方法 描述 示例
String group() 返回当前匹配到的整个子串 如果模式是 (\\d+)-(\\d+),匹配 "123-456",group() 返回 "123-456"
String group(int groupIndex) 返回指定捕获组匹配到的子串,索引从 1 开始。group(0) 等同于 group() 在 "123-456" 中,group(1) 返回 "123",group(2) 返回 "456"
int start() 返回当前匹配子串的起始索引(在输入字符串中的位置)。 匹配 "cat" 在 "my cat is cute" 中,start() 返回 3
int end() 返回当前匹配子串的结束索引的下一个位置,即 end()substring(start, end) 的结束索引。 匹配 "cat" 在 "my cat is cute" 中,end() 返回 6
int start(int groupIndex) 返回指定捕获组的起始索引。 在 "123-456" 中,start(1) 返回 0,start(2) 返回 4
int end(int groupIndex) 返回指定捕获组的结束索引的下一个位置。 在 "123-456" 中,end(1) 返回 3,end(2) 返回 7

替换方法

方法 描述 示例
String replaceAll(String replacement) 替换输入字符串中所有匹配的子串为 replacement 字符串。 将字符串中所有 "cat" 替换为 "dog"
String replaceFirst(String replacement) 替换输入字符串中第一个匹配的子串为 replacement 字符串。 将字符串中第一个 "cat" 替换为 "dog"
Matcher appendReplacement(StringBuffer sb, String replacement) 一个更强大的替换方法,用于构建复杂的替换结果,它会将上次匹配到当前匹配之间的文本,以及替换后的文本追加到 StringBuffer 中。 通常与 appendTail() 结合使用,实现灵活替换
Matcher appendTail(StringBuffer sb) appendReplacement 之后,将剩余的未匹配部分追加到 StringBuffer 中。 完成整个替换过程

重置方法

方法 描述 示例
Matcher reset() 重置 Matcher 的状态,使其可以重新从输入字符串的开头开始查找。 find() 循环结束后,如果想重新查找一遍,可以调用此方法
Matcher reset(CharSequence input) 重置 Matcher 并为其设置一个新的输入字符串。 复用同一个 Matcher 实例来处理不同的输入

代码示例

示例 1:查找所有匹配项并获取捕获组

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherExample1 {
    public static void main(String[] args) {
        String text = "John's phone is 123-456-7890, and Jane's is 987-654-3210.";
        String regex = "(\\d{3})-(\\d{3})-(\\d{4})"; // 匹配美国电话号码格式
        // 1. 编译 Pattern
        Pattern pattern = Pattern.compile(regex);
        // 2. 创建 Matcher
        Matcher matcher = pattern.matcher(text);
        System.out.println("查找所有电话号码:");
        // 3. 使用 find() 循环查找所有匹配
        while (matcher.find()) {
            // 获取整个匹配的字符串
            System.out.println("找到完整号码: " + matcher.group());
            // 获取第一个捕获组 (区号)
            System.out.println("  区号: " + matcher.group(1));
            // 获取第二个捕获组 (交换码)
            System.out.println("  交换码: " + matcher.group(2));
            // 获取第三个捕获组 (号码)
            System.out.println("  号码: " + matcher.group(3));
            System.out.println("  起始位置: " + matcher.start() + ", 结束位置: " + matcher.end());
            System.out.println("--------------------");
        }
    }
}

输出:

查找所有电话号码:
找到完整号码: 123-456-7890
  区号: 123
  交换码: 456
  号码: 7890
  起始位置: 13, 结束位置: 25
--------------------
找到完整号码: 987-654-3210
  区号: 987
  交换码: 654
  号码: 3210
  起始位置: 38, 结束位置: 50
--------------------

示例 2:matches() vs lookingAt()

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherExample2 {
    public static void main(String[] args) {
        String text1 = "hello world";
        String text2 = "hello there, world";
        String regex = "hello.*";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher1 = pattern.matcher(text1);
        Matcher matcher2 = pattern.matcher(text2);
        System.out.println("模式: " + regex);
        System.out.println("文本1: " + text1);
        System.out.println("文本2: " + text2);
        System.out.println("\n--- matches() (整个字符串必须匹配) ---");
        System.out.println("text1.matches(): " + matcher1.matches()); // true
        System.out.println("text2.matches(): " + matcher2.matches()); // false, 因为后面还有 ", world"
        System.out.println("\n--- lookingAt() (从开头匹配即可) ---");
        System.out.println("text1.lookingAt(): " + matcher1.lookingAt()); // true
        System.out.println("text2.lookingAt(): " + matcher2.lookingAt()); // true
    }
}

示例 3:替换操作

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherExample3 {
    public static void main(String[] args) {
        String text = "apple banana apple orange apple";
        String regex = "apple";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        System.out.println("原始文本: " + text);
        // replaceAll
        String replacedAll = matcher.replaceAll("grape");
        System.out.println("replaceAll 结果: " + replacedAll); // grape banana grape orange grape
        // reset matcher to use it again
        matcher.reset();
        // replaceFirst
        String replacedFirst = matcher.replaceFirst("grape");
        System.out.println("replaceFirst 结果: " + replacedFirst); // grape banana apple orange apple
    }
}

重要提示:group(0) vs group()

Matcher 中,group(0)group() 完全等价,都代表当前匹配的整个子串,这与一些其他语言(如 Python)的 group(0) 表示整个匹配,而 group() 表示第一个捕获组不同,在 Java 中,group() group(0)

  • Pattern静态的、编译后的规则
  • Matcher动态的、用于执行匹配操作的对象
  • find() 是循环查找多个匹配项的核心。
  • matches() 用于验证整个字符串格式。
  • group()group(int) 用于提取匹配到的内容,特别是捕获组。
  • replaceAll()replaceFirst() 是最简单的替换方法。

熟练掌握 Matcher 的这些方法,你就可以在 Java 中灵活地处理各种复杂的字符串匹配、提取和替换任务。

分享:
扫描分享到社交APP
上一篇
下一篇