String.replaceAll()

String.replaceAll()

String.replaceAll() 方法的定义和实现是这样的:

1
2
3
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

第1个参数是正则表达式,第2个参数则是替换的字符串。

但并不是那么简单,实际上存在着坑点,方法注释里面说到:

1
2
3
Note that backslashes ({@code \}) and dollar signs ({@code $}) in the
replacement string may cause the results to be different than if it were
being treated as a literal replacement string;

简单点说,就是第2个参数 replacement 中,如果包含斜杠 \ 或者 $,那么它就不仅仅是一个普通的替换字符串。

一、特殊字符 $

$ 在参数 replacement 中是特殊字符,可用于表示第1个正则参数匹配的子串。

比如说,$0 表示匹配的第一个子串:

1
2
String s = "abc";                // abc
s = s.replaceAll("b", ", $0, "); // a, b, c

第2个参数中的 $0 实际就是正则匹配子串 b

所以,$ 在参数 replacement 中算是比较特殊的存在。

二、转义字符 \

那如果确实是要替换字符 $,怎么办?

那就是用转义字符 \,把 $ 换成 \$$ 就会被认为是普通字符了。

比如这样:

1
2
String s = "abc";                 // abc
s = s.replaceAll("b", ", \\$, "); // a, $, c

因此,参数 replacement 里面的斜杠 \ 也是特殊字符,是专门用于转义的。

所以,\ 出现在参数 replacement 时也需要注意转义的情况。

比如说,想要把 a,b,c 里面的 , 替换成 \,下面这种写法是不行的:

1
2
String s = "a,b,c";          // a,b,c
s = s.replaceAll(",", "\\"); // character to be escaped is missing

直接报错了,这是为什么?

  • 首先,在 java 字符串表达式中,表示一个 \ 字符,本身就需要转义,写成 \\
  • 其次,replacement 这个参数自己也需要转义,所以还要给 \\ 再转义,写成 \\\\ 才行

所以,下面这种写法才是正常的:

1
2
String s = "a,b,c";            // a,b,c
s = s.replaceAll(",", "\\\\"); // a\b\c

总的来说,String.replaceAll() 方法的第二个参数 replacement 虽然不是正则表达式,但也是一种特殊的表达式,需要对 \$ 进行转义,所以写的时候会比一般字符串表达式写多一层转义。

作者

jiaduo

发布于

2023-01-09

更新于

2023-04-02

许可协议