为什么replaceAll会因"非法组参考"而失败?

Sat*_*k k 59 java regex

我需要更换

\\\s+\\$\\$ to $$
Run Code Online (Sandbox Code Playgroud)

我用了

String s = "  $$";
s = s.replaceAll("\\s+\\$\\$","$$");
Run Code Online (Sandbox Code Playgroud)

但它会抛出异常

java.lang.IllegalArgumentException:非法组引用

And*_*rey 85

来自String#replaceAll javadoc:

请注意,替换字符串中的反斜杠(\)和美元符号($)可能会导致结果与将其视为文字替换字符串时的结果不同; 见Matcher.replaceAll.如果需要,使用Matcher.quoteReplacement(java.lang.String)来抑制这些字符的特殊含义.

因此,使用Matcher#quoteReplacement可以完成任意替换字符串的转义:

String s = "  $$";
s = s.replaceAll("\\s+\\$\\$", Matcher.quoteReplacement("$$"));
Run Code Online (Sandbox Code Playgroud)

也可以使用Pattern#quote完成模式的转义

String s = "  $$";
s = s.replaceAll("\\s+" + Pattern.quote("$$"), Matcher.quoteReplacement("$$"));
Run Code Online (Sandbox Code Playgroud)

  • 由于替换字符串的未知数为99.99_9%,因此此答案的含义要多得多。 (2认同)
  • 唯一的问题是,`String.replaceAll(regexp,replacement)`并没有说明它将替换字符串作为幕后的正则表达式处理。作为一名程序员,我可能会对使用regexp进行匹配感兴趣,而对于使用文字进行替换感兴趣-如果API文档中没有相应的提示,我希望这会发生。 (2认同)

Koe*_*err 49

使用"\\$\\$"第二个参数:

String s="  $$";
s=s.replaceAll("\\s+\\$\\$","\\$\\$");
//or
//s=s.replaceAll("\\s+\\Q$$\\E","\\$\\$");
Run Code Online (Sandbox Code Playgroud)

$是组符号正则表达式的替代参数

所以你需要逃避它


Hen*_*ann 6

这里的问题不是正则表达式,而是替换:

$用于表示()匹配组.因此你需要使用反斜杠(以及第二个反斜杠以使java编译器满意)来逃避它:

String s="  $$";
s = s.replaceAll("\\s+\\$\\$", "\\$\\$");
Run Code Online (Sandbox Code Playgroud)