核心方法概览
-
String.replaceAll(String regex, String replacement)- 功能: 将字符串中所有匹配正则表达式的子字符串替换为指定的
replacement字符串。 - 返回值: 一个新的字符串,替换完成后的结果。
- 特点: 简单易用,适用于全局替换。
- 功能: 将字符串中所有匹配正则表达式的子字符串替换为指定的
-
String.replaceFirst(String regex, String replacement)- 功能: 将字符串中第一个匹配正则表达式的子字符串替换为指定的
replacement字符串。 - 返回值: 一个新的字符串,替换完成后的结果。
- 特点: 适用于只替换第一个匹配项的场景。
- 功能: 将字符串中第一个匹配正则表达式的子字符串替换为指定的
-
Matcher.appendReplacement(StringBuffer sb, String replacement)- 功能: 这是
java.util.regex.Matcher类中的核心方法,用于执行复杂的替换操作。 - 工作方式: 它会从当前匹配位置开始,将上一个匹配结束位置到当前匹配开始位置之间的文本(即未匹配的部分)追加到
StringBuffer中,然后将replacement字符串追加进去,并更新Matcher的状态,使其指向下一个匹配位置。 - 特点: 非常灵活,可以在替换过程中引用分组,并且可以结合循环进行多次替换。
- 功能: 这是
-
Matcher.appendTail(StringBuffer sb)- 功能: 在
appendReplacement()循环结束后,将最后一个匹配项之后的所有剩余文本追加到StringBuffer中。 - 特点: 必须在
appendReplacement()循环之后调用,以完成整个字符串的构建。
- 功能: 在
replaceAll() 和 replaceFirst() - 简单直接
这是最常用的方法,语法简单,适合大多数场景。
replaceAll() 示例
public class RegexReplaceExample {
public static void main(String[] args) {
String text = "Hello 123 World 456, and 789.";
// 目标:将所有的数字替换为 "[NUMBER]"
String regex = "\\d+"; // \d+ 匹配一个或多个数字
String replacement = "[NUMBER]";
String result = text.replaceAll(regex, replacement);
System.out.println("原始文本: " + text);
System.out.println("替换后文本: " + result);
// 输出: 替换后文本: Hello [NUMBER] World [NUMBER], and [NUMBER].
}
}
replaceFirst() 示例
public class RegexReplaceFirstExample {
public static void main(String[] args) {
String text = "apple banana apple cherry";
// 目标:只替换第一个 "apple"
String regex = "apple";
String replacement = "orange";
String result = text.replaceFirst(regex, replacement);
System.out.println("原始文本: " + text);
System.out.println("替换后文本: " + result);
// 输出: 替换后文本: orange banana apple cherry
}
}
Matcher 类的替换方法 - 高度灵活
当你需要更复杂的逻辑时,比如在替换字符串中引用匹配到的分组,或者想对匹配到的内容进行二次处理,就必须使用 Matcher 类。
核心步骤:
- 编译正则表达式,得到
Pattern对象。 - 用
Pattern对象和原始文本创建Matcher对象。 - 创建一个
StringBuffer用于存储结果。 - 使用
while (matcher.find())循环查找所有匹配项。 - 在循环内调用
matcher.appendReplacement(sb, replacement)。 - 循环结束后,调用
matcher.appendTail(sb)。 - 从
StringBuffer中获取最终结果。
示例:在替换中引用分组
这是一个非常经典和有用的功能,在 replacement 字符串中,可以使用 $n 来引用第 n 个分组(从1开始)。
场景:将格式为 "姓氏,名字" 的文本转换为 "名字 姓氏"。
import java.util.regex.*;
public class MatcherReplaceWithGroupExample {
public static void main(String[] args) {
String text = "Doe,John; Smith,Jane; Watson,Sherlock";
// 正则表达式: 捕获姓氏和名字
// (\\w+) 匹配并捕获姓氏
// ,\\s* 匹配逗号和可能的空格
// (\\w+) 匹配并捕获名字
String regex = "(\\w+),\\s*(\\w+)";
// 替换字符串: $2 对应第二个分组 (名字), $1 对应第一个分组 (姓氏)
String replacement = "$2 $1";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuffer sb = new StringBuffer();
// 循环查找并替换所有匹配项
while (matcher.find()) {
// 将 "Doe,John" 替换为 "John Doe"
matcher.appendReplacement(sb, replacement);
}
// 将剩余部分(如最后的分号)追加到结果中
matcher.appendTail(sb);
String result = sb.toString();
System.out.println("原始文本: " + text);
System.out.println("替换后文本: " + result);
// 输出: 替换后文本: John Doe; Jane Smith; Sherlock Watson
}
}
示例:动态生成替换内容
如果你想根据匹配到的内容动态决定替换什么,可以在 appendReplacement 循环内部进行判断。
场景:将文本中的所有数字替换为其对应的英文单词,但只替换两位数(10-99)。
import java.util.regex.*;
public class DynamicReplacementExample {
public static void main(String[] args) {
String text = "I have 5 apples, 12 oranges, and 99 bananas.";
String regex = "\\d+"; // 匹配所有数字
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String matchedNumber = matcher.group(); // 获取匹配到的字符串,如 "12"
int num = Integer.parseInt(matchedNumber);
String replacement;
if (num >= 10 && num <= 99) {
// 动态生成替换内容
replacement = getNumberInWords(num);
} else {
// 不满足条件,替换为原样
replacement = matchedNumber;
}
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
System.out.println("原始文本: " + text);
System.out.println("替换后文本: " + sb.toString());
// 输出: 替换后文本: I have 5 apples, twelve oranges, and ninety-nine bananas.
}
// 一个简单的辅助方法,将两位数转为英文单词(简化版)
private static String getNumberInWords(int num) {
String[] tens = {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};
String[] ones = {"", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
if (num < 10 || num > 99) return String.valueOf(num);
int tenDigit = num / 10;
int oneDigit = num % 10;
if (oneDigit == 0) {
return tens[tenDigit];
} else {
return tens[tenDigit] + "-" + ones[oneDigit];
}
}
}
重要注意事项
反斜杠 \ 的双重转义
在 Java 字符串中,反斜杠 \ 是一个转义字符,所以当你想在正则表达式中使用 \d (表示数字) 时,必须在 Java 字符串中写成 "\\d"。
- 正则表达式:
\d+ - Java 字符串:
"\\d+"
在 replacement 字符串中的特殊含义
在 replaceAll 和 appendReplacement 的 replacement 参数中, 是一个特殊字符,用于引用分组。
$1,$2, ...: 引用第1, 2, ...个分组。$0: 引用整个匹配的子串。
如果你想在替换字符串中插入一个字面的 符号,你需要对它进行转义,写成 \$。
示例:
String text = "price: 100";
// 错误用法: 会抛出 IllegalArgumentException,因为 "$100" 试图引用一个不存在的第100个分组
// String result = text.replaceAll("\\d", "$100");
// 正确用法: 插入一个字面的 '$'
String result = text.replaceAll("\\d", "\\$$0"); // $0 代表整个匹配的数字
System.out.println(result); // 输出: price: $100
| 方法 | 用途 | 简单性 | 灵活性 |
|---|---|---|---|
replaceAll() |
全局替换 | 高 | 中 (支持 $n 分组引用) |
replaceFirst() |
替换第一个匹配项 | 高 | 中 (支持 $n 分组引用) |
Matcher.appendReplacement() |
复杂、动态替换 | 低 | 高 (可循环、可编程、支持 $n) |
- 日常使用:优先选择
replaceAll()和replaceFirst(),它们简洁明了。 - 高级需求:当需要引用分组、动态生成替换内容或对匹配项进行复杂处理时,使用
Matcher类的appendReplacement()和appendTail()方法。
