Java 逐次替换 appendReplacement

Last Modified: 2023/08/23

什么是逐次替换

有时候可能需要对匹配上的内容,依次替换不同的内容,这便是逐次替换。例如:一个字符串 a[1]b[2]c[3],我们需要将 [] 中的数字 1、2、3 依次替换成 11、22 和 33。

这个实现很简单,但是使用的不多,时常容易忘记,逐次替换的方法如下:

StringBuffer sb = new StringBuffer();
Matcher matcher = Pattern.compile("\\d+").matcher("a[1]b[2]c[3]");
while (matcher.find()) {
    // matcher.group() 便是 \\d+ 匹配的数字
    matcher.appendReplacement(sb, matcher.group() + matcher.group());
}
matcher.appendTail(sb);
// 输出 a[11]b[22]c[33]
System.out.println(sb);

逐次替换是一个固定的套路写法,但是逐次替换平时的实在不多,容易遗忘具体写法,因此有必要对这个固定的套路进行封装。

封装逐次替换

可以封装一个函数 replace,接收一个输入字符串和正则表达式,第三个参数是一个 lambda 表达式,作用是提供逐次替换的具体内容。replace 函数签名如下:

public static StringBuffer replace(String regex, String input, ReplacementSupplier s);

@FunctionalInterface
public interface ReplacementSupplier {
    String provide(Matcher m, String currentMatch, int index);
}

ReplacementSupplier 是一个 FunctionalInterface,作用是提供逐次替换的内容,但是逐次替换的内容一般是根据当前匹配的内容或者当前匹配的位置来决定的,因此这个函数提供了 currentMatch 和 index 分别表示当前匹配的内容和当前是第几次匹配。可以根据这两个参数来决定替换的内容。

replace 函数实现如下:

public static StringBuffer replace(String regex, String input, ReplacementSupplier s) {
    StringBuffer sb = new StringBuffer();
    Matcher matcher = Pattern.compile(regex).matcher(input);
    int i = 0;
    while (matcher.find()) {
        String replacement = s.provide(matcher, matcher.group(), i++);
        if (replacement == null) {
            break;
        }
        matcher.appendReplacement(sb, replacement);
    }
    matcher.appendTail(sb);
    return sb;
}

下面使用封装后的 replace 函数来实现上一节的需求

StringBuffer ret = replace("\\d+", "a[1]b[2]c[3]", (m, currentMatch, index) -> {
    System.out.println("currentMatch: " + currentMatch + ",index: " + index);
    return currentMatch + currentMatch;
});
System.out.println(ret);

输出如下:

currentMatch: 1,index: 0
currentMatch: 2,index: 1
currentMatch: 3,index: 2
a[11]b[22]c[33]

index 表示当前是第几次匹配,currentMatch 表示当前匹配的内容是啥,从上面的输出可以看出,第一次匹配的内容为 1,第二次匹配的内容为 2,第三次匹配的内容为 3

有问题吗?点此反馈!

温馨提示:反馈需要登录