详细解释 Java 中 Matcher.appendReplacement() 和 Matcher.appendTail() 这两个重要的字符串处理方法。
1. Matcher.appendReplacement()
功能描述
appendReplacement() 方法用于在匹配到模式时,将匹配结果之前的文本和替换后的文本追加到 StringBuffer 中。
方法签名
public Matcher appendReplacement(StringBuffer sb, String replacement)
工作原理
- 从上次匹配结束位置到当前匹配开始位置之间的文本被追加到 StringBuffer
- 将替换字符串(可以包含反向引用)追加到 StringBuffer
- 更新匹配位置
替换字符串中的特殊字符
$n- 引用第 n 个捕获组(n 为 1-9)$0- 引用整个匹配$<name>- 引用命名捕获组(Java 7+)\\- 转义字符
2. Matcher.appendTail()
功能描述
appendTail() 方法用于在完成所有替换后,将剩余未处理的文本追加到 StringBuffer 中。
方法签名
public StringBuffer appendTail(StringBuffer sb)
3. 完整示例
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class AppendReplacementExample {
public static void main(String[] args) {
String input = "The quick brown fox jumps over the lazy dog";
String regex = "\\b\\w{4}\\b"; // 匹配4个字母的单词
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
StringBuffer result = new StringBuffer();
// 使用 appendReplacement 进行替换
while (matcher.find()) {
//获取匹配到的字符串
String matchedWord = matcher.group();
//替换为大写
String replacement = "[" + matchedWord.toUpperCase() + "]";
System.out.println("找到匹配: '" + matchedWord + "',位置: " +
matcher.start() + "-" + matcher.end());
matcher.appendReplacement(result, replacement);
System.out.println("当前结果: " + result.toString());
}
// 使用 appendTail 完成处理
matcher.appendTail(result);
System.out.println("\n最终结果: " + result.toString());
}
}
输出:
找到匹配: 'quick',位置: 4-9
当前结果: The [QUICK]
找到匹配: 'jumps',位置: 20-25
当前结果: The [QUICK] brown fox [JUMPS]
找到匹配: 'over',位置: 26-30
当前结果: The [QUICK] brown fox [JUMPS] [OVER]
找到匹配: 'lazy',位置: 35-39
当前结果: The [QUICK] brown fox [JUMPS] [OVER] the [LAZY]
最终结果: The [QUICK] brown fox [JUMPS] [OVER] the [LAZY] dog
4. 使用反向引用的示例
public class BackReferenceExample {
public static void main(String[] args) {
String input = "John Smith, Jane Doe, Bob Johnson";
String regex = "(\\w+) (\\w+)"; // 捕获名和姓
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
StringBuffer result = new StringBuffer();
// 交换名和姓的位置,并添加格式
while (matcher.find()) {
// $2 引用第二个捕获组(姓),$1 引用第一个捕获组(名)
matcher.appendReplacement(result, "$2, $1");
}
matcher.appendTail(result);
System.out.println("原始: " + input);
System.out.println("处理后: " + result.toString());
}
}
输出:
原始: John Smith, Jane Doe, Bob Johnson
处理后: Smith, John, Doe, Jane, Johnson, Bob
5. 更复杂的替换示例
public class ComplexReplacement {
public static void main(String[] args) {
String html = "<p>价格: $10.50</p><div>总计: $25.00</div>";
String regex = "\\$([0-9]+\\.[0-9]{2})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(html);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
double amount = Double.parseDouble(matcher.group(1));
double converted = amount * 0.85; // 假设汇率转换
String replacement = String.format("€%.2f", converted);
matcher.appendReplacement(result, replacement);
}
matcher.appendTail(result);
System.out.println("原始HTML: " + html);
System.out.println("转换后: " + result.toString());
}
}
输出:
原始HTML: <p>价格: $10.50</p><div>总计: $25.00</div>
转换后: <p>价格: €8.93</p><div>总计: €21.25</div>
6. 实用工具方法示例
public class RegexUtils {
/**
* 自定义替换方法,使用函数式接口处理每个匹配
*/
public static String replaceAll(String input, String regex,
java.util.function.Function<String, String> replacer) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
String replacement = replacer.apply(matcher.group());
matcher.appendReplacement(result, replacement);
}
matcher.appendTail(result);
return result.toString();
}
public static void main(String[] args) {
String text = "我的电话是123-4567,另一个是890-1234";
// 使用lambda表达式进行替换
String masked = replaceAll(text, "\\d{3}-\\d{4}",
match -> "***-****");
System.out.println("原始: " + text);
System.out.println("脱敏后: " + masked);
}
}
关键要点
- 必须配合使用:
appendReplacement()和appendTail()通常一起使用 - 状态维护:
appendReplacement()会维护匹配位置状态 - 性能优势: 对于大文本,比
String.replaceAll()更高效 - 灵活性: 支持复杂的替换逻辑和反向引用
- 线程安全: 单个 Matcher 实例不是线程安全的
这两个方法为复杂的字符串替换操作提供了强大而灵活的工具。
1万+

被折叠的 条评论
为什么被折叠?



