核心概念
replaceAll() 方法是 Java String 类的一个方法,它使用给定的正则表达式(Regular Expression)来匹配字符串中的所有子字符串,并将其替换为指定的替换字符串。

方法签名:
public String replaceAll(String regex, String replacement)
regex: 你要匹配的模式,这是一个正则表达式,而不仅仅是普通字符串。replacement: 用于替换匹配项的字符串,这个字符串可以包含特殊的反向引用序列。
replaceAll() 与 replace() 的关键区别
很多初学者会混淆 replaceAll() 和 replace()。
| 特性 | replaceAll(String regex, String replacement) |
replace(CharSequence target, CharSequence replacement) |
|---|---|---|
| 第一个参数 | 正则表达式 | 普通字符串 |
| 功能 | 根据正则表达式匹配规则进行查找和替换 | 查找完全匹配的普通子字符串并替换 |
| 转义字符 | 正则表达式中的特殊字符(如 , , 等)需要转义 | 无需考虑正则表达式,只需考虑 Java 字符串本身的转义 |
| 示例 | str.replaceAll("\\.", "点") |
str.replace(".", "点") |
- 如果你的查找模式是固定的、简单的字符串,用
replace(),它更直接、性能也稍好。 - 如果你的查找模式有规律(所有数字、所有空格、特定格式的文本),就必须用
replaceAll()并配合正则表达式。
正则表达式中的特殊字符(元字符)
正则表达式由两种字符组成:

- 普通字符:如
a,b,1, 等,它们代表自身。 - 特殊字符(元字符):如
^\[]等,它们有特殊的含义。
理解这些元字符是使用 replaceAll() 的基础。
| 元字符 | 名称 | 含义 | 示例 |
|---|---|---|---|
| 点 | 匹配除换行符外的任何单个字符 | a.c 匹配 "abc", "aac", "a!c" |
|
| 星号 | 匹配前面的元素零次或多次 | a*b 匹配 "b", "ab", "aaaab" |
|
| 加号 | 匹配前面的元素一次或多次 | a+b 匹配 "ab", "aaaab",但不匹配 "b" |
|
| 问号 | 匹配前面的元素零次或一次 | a?b 匹配 "b", "ab" |
|
^ |
脱字符 | 匹配行的开头 | ^hello 匹配 "hello world" 的开头,但不匹配 "say hello" |
| 美元符 | 匹配行的结尾 | world$ 匹配 "hello world" 的结尾 |
|
\d |
数字 | 匹配任意一个数字 [0-9] |
\d\d 匹配 "12", "99" |
\D |
非数字 | 匹配任意一个非数字字符 | \D\D 匹配 "ab", "$#" |
\w |
单词字符 | 匹配 [a-zA-Z0-9_] |
\w\w 匹配 "a1", "B_" |
\W |
非单词字符 | 匹配 \w 之外的任何字符 |
\W\W 匹配 "!@", " - " |
\s |
空白字符 | 匹配空格、制表符、换行符等 [ \t\n\r\f] |
\s+ 匹配 " ", " ", "\t" |
\S |
非空白字符 | 匹配任何非空白字符 | \S\S 匹配 "a1", "b@" |
[] |
字符类 | 匹配方括号内的任意一个字符 | [abc] 匹配 "a", "b", 或 "c" |
[^] |
否定字符类 | 匹配任何不在方括号内的字符 | [^abc] 匹配 "d", "1", "@" |
| 捕获组 | 将括号内的内容作为一个整体,并创建一个反向引用 | (\d{3})-(\d{4}) |
|
{n,m} |
量词 | 匹配前面的元素至少 n 次,最多 m 次 |
\d{2,4} 匹配 2 到 4 位数字 |
替换字符串中的特殊字符:反向引用
replaceAll 的第二个参数 replacement 字符串中也可以包含特殊字符,最主要的就是反向引用。
反向引用允许你引用在正则表达式中用 捕获的分组。
| 序列 | 含义 |
|---|---|
$0 |
整个匹配的字符串 |
$1 |
第一个捕获组匹配的字符串 |
$2 |
第二个捕获组匹配的字符串 |
| ... | ... |
示例:交换名字和姓氏

String str = "Doe, John";
// 目标是变成 "John Doe"
// (.*) 匹配 "Doe, ",第二个 (.*) 匹配 "John"
String result = str.replaceAll("^(.*), (.*)$", "$2 $1");
System.out.println(result); // 输出: John Doe
解释:
^(.*), (.*)$:^: 匹配字符串开头。- 第一个捕获组,匹配任意字符(除换行符)零次或多次。
,\s*: 匹配一个逗号和可能的空格。- 第二个捕获组,匹配名字。
- 匹配字符串结尾。
"$2 $1":$2引用第二个捕获组的内容,即 "John"。$1引用第一个捕获组的内容,即 "Doe"。- 最终用 "John Doe" 替换了原始字符串 "Doe, John"。
常见陷阱与解决方案
陷阱1:忘记在 Java 字符串中转义反斜杠 \
在 Java 字符串中,反斜杠 \ 本身是一个转义字符,要在字符串中表示一个正则表达式的 \d,你需要在 Java 字符串中写成 "\\d"。
错误示例:
// 错误!\d 会被 Java 解释为转义字符 'd',这是一个无效的转义序列
String result = "abc123".replaceAll("\d", "");
正确示例:
// 正确!第一个 \ 是转义字符,用来在字符串中表示第二个 \
String result = "abc123".replaceAll("\\d", "");
System.out.println(result); // 输出: abc
陷阱2:混淆 和 \$
在正则表达式中, 是一个元字符,表示行尾,如果你想在替换字符串中直接使用一个 符号,而不是作为反向引用的开头,你需要用反斜杠 \ 对其进行转义。
示例:将价格格式化成 "价格: $100"
String price = "100";
// 错误:$1 会被解释为反向引用,但这里没有捕获组,会抛出异常
// String result = "价格: $".replaceAll("$", "$1");
// 正确:\$ 会被当作一个普通的 '$' 字符
String result = "价格: $".replaceAll("\\$", "") + price;
System.out.println(result); // 输出: 价格: 100
// 更好的方式是直接拼接
String result2 = "价格: $" + price;
System.out.println(result2); // 输出: 价格: $100
实用示例
示例1:移除所有非数字字符
String text = "电话: 138-1234-5678";
String onlyNumbers = text.replaceAll("\\D", "");
System.out.println(onlyNumbers); // 输出: 13812345678
示例2:规范化空白字符 将多个连续的空格、制表符、换行符替换成一个空格。
String messyText = "这是一个 \t 测试\n字符串。";
String cleanText = messyText.replaceAll("\\s+", " ");
System.out.println(cleanText); // 输出: 这是一个 测试 字符串。 