杰瑞科技汇

Java正则表达式replaceAll如何替换特定模式?

String.replaceAll()

String.replaceAll() 是 Java String 类的一个方法,用于替换字符串中所有匹配正则表达式的子串。

Java正则表达式replaceAll如何替换特定模式?-图1
(图片来源网络,侵删)

方法签名

public String replaceAll(String regex, String replacement)
  • regex (正则表达式): 你要查找的模式的字符串描述。这里的关键是,它是一个正则表达式,而不仅仅是普通文本。
  • replacement (替换字符串): 用来替换匹配项的字符串,这个字符串中可以使用特殊的“反向引用”语法。

工作原理与示例

replaceAll 会遍历整个字符串,找到所有与 regex 匹配的子串,然后用 replacement 字符串替换它们。

示例 1:简单的文本替换

即使不使用正则表达式的特性,replaceAll 也可以像 replace 一样工作。

String str = "Hello World, Hello Java";
// 将所有的 "Hello" 替换为 "Hi"
String result = str.replaceAll("Hello", "Hi");
System.out.println(result); // 输出: Hi World, Hi Java

示例 2:使用正则表达式进行模式匹配

这才是 replaceAll 的真正威力所在,假设我们想移除字符串中所有的数字。

String str = "我的电话是138-1234-5678,请拨打!";
// 正则表达式 \d 匹配任何数字 [0-9]
// + 表示一个或多个
String result = str.replaceAll("\\d+", "");
System.out.println(result); // 输出: 我的电话是-,请拨打!

注意: 在 Java 字符串中,反斜杠 \ 是一个转义字符,要表示正则表达式中的 \d,你需要在 Java 字符串中写成 \\d,这是一个非常常见的初学者错误。

Java正则表达式replaceAll如何替换特定模式?-图2
(图片来源网络,侵删)

关键特性:反向引用 ($1, $2, ...)

这是 replaceAll 最强大也最容易混淆的功能,在 replacement 字符串中,你可以使用 $n 来引用正则表达式中的“捕获组”(capturing group)。

什么是捕获组?

用圆括号 括起来的正则表达式部分就是一个捕获组,在 (\d{3})-(\d{4}) 中:

  • (\d{3}) 是第一个捕获组(匹配3个数字)。
  • (\d{4}) 是第二个捕获组(匹配4个数字)。

反向引用如何工作?

replacement 字符串中:

  • $1 会被替换为第一个捕获组匹配到的内容。
  • $2 会被替换为第二个捕获组匹配到的内容。
  • 以此类推。

示例 3:交换日期格式

假设我们有 YYYY-MM-DD 格式的日期,想把它转换成 DD/MM/YYYY 格式。

Java正则表达式replaceAll如何替换特定模式?-图3
(图片来源网络,侵删)
String dateStr = "2025-10-27";
// 正则表达式解释:
// (\d{4})  -> 捕获组1: 匹配4个数字 (年份)
// -        -> 匹配字面量 "-"
// (\d{2})  -> 捕获组2: 匹配2个数字 (月份)
// -        -> 匹配字面量 "-"
// (\d{2})  -> 捕获组3: 匹配2个数字 (日期)
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
// 替换字符串解释:
// $3/$2/$1 -> 用捕获组3(日), 捕获组2(月), 捕获组1(年) 来构建新字符串
String replacement = "$3/$2/$1";
String result = dateStr.replaceAll(regex, replacement);
System.out.println(result); // 输出: 27/10/2025

常见陷阱与注意事项

陷阱 1:混淆 replaceAllreplace

方法 参数类型 是否支持正则表达式 示例
replaceAll (String regex, String replacement) s.replaceAll("\\s+", " ")
replace (CharSequence target, CharSequence replacement) s.replace(" ", " ")

错误示例:

// 错误意图:想把所有的 "." 替换成 "-"
String ip = "192.168.1.1";
// . 在正则表达式里是“任意字符”的意思,所以这行代码会报错或产生意外结果
// String wrong = ip.replace(".", "-"); // 这个是OK的,因为replace不支持正则
String right = ip.replaceAll("\\.", "-"); // 必须对 . 进行转义
System.out.println(right); // 输出: 192-168-1-1

陷阱 2:忘记在 Java 字符串中转义反斜杠

这是最最最常见的错误。

你想写的正则表达式 在 Java 字符串中应该怎么写 解释
\d (匹配数字) "\\d" 第一个 \ 转义了第二个 \,最终编译器看到的是 \d
\s (匹配空白) "\\s" 同上
(匹配任意字符) "\\." 第一个 \ 转义了第二个 ,使其匹配字面量 "."
\\ (匹配反斜杠) "\\\\" 第一个 \ 转义第二个 \,编译器看到的是 \

陷阱 3:反向引用的语法错误

  • 错误: 使用 $0$0 指的是整个匹配的字符串,而不是第0个捕获组(捕获组从1开始计数)。
  • 错误: 使用 \1,在 replacement 字符串中,反向引用必须使用 符号,而不是 \\1 是在正则表达式本身内部使用的。

陷阱 4:贪婪模式 vs. 懒惰模式

正则表达式默认是“贪婪”的,它会匹配尽可能多的字符。

String html = "<div>第一段</div><div>第二段</div>";
// 贪婪模式: .* 会匹配从第一个 <div> 开始到最后一个 </div> 结束的所有内容
String greedyResult = html.replaceAll("<div>.*</div>", "REPLACED");
System.out.println("贪婪模式结果: " + greedyResult);
// 输出: 贪婪模式结果: REPLACED
// (只替换了一次,因为 .* 匹配了中间的所有内容)
// 懒惰模式: .*? 会匹配尽可能少的字符
String lazyResult = html.replaceAll("<div>.*?</div>", "REPLACED");
System.out.println("懒惰模式结果: " + lazyResult);
// 输出: 懒惰模式结果: REPLACEDREPLACED
// (替换了两次,因为 .*? 在第一个 </div> 处就停止了)
  • 是贪婪量词。
  • 是懒惰量词。

实用案例

案例 1:清理日志字符串

移除多余的空格和换行符。

String log = "  ERROR  [main]  This is a  test message.  \n";
// \\s+ 匹配一个或多个空白字符(空格、制表符、换行符等)
String cleanedLog = log.replaceAll("\\s+", " ").trim();
System.out.println(cleanedLog); // 输出: ERROR [main] This is a test message.

案例 2:脱敏处理

隐藏手机号码中间四位。

String phone = "用户手机号是13812345678。";
// 正则表达式解释:
// (\d{3}) -> 捕获前3位
// \d{4}   -> 匹配中间4位(不捕获)
// (\d{4}) -> 捕获后4位
String regex = "(\\d{3})\\d{4}(\\d{4})";
// 替换为:捕获组1 + **** + 捕获组2
String replacement = "$1****$2";
String maskedPhone = phone.replaceAll(regex, replacement);
System.out.println(maskedPhone); // 输出: 用户手机号是138****5678。
  • replaceAll 是基于正则表达式的替换工具。
  • regex 参数是正则表达式,注意 Java 字符串中的反斜杠需要转义(\\d)。
  • replacement 参数可以使用 $n 语法来引用正则表达式中的捕获组 `(...
分享:
扫描分享到社交APP
上一篇
下一篇