为什么replaceAll失败并显示“非法组引用”?


69

我需要更换

\\\s+\\$\\$ to $$

我用了

String s = "  $$";
s = s.replaceAll("\\s+\\$\\$","$$");

但它引发异常

java.lang.IllegalArgumentException:非法的组引用


我在遇到完全相同的问题replaceFirst()。以下答案也有帮助。
kevinarpe19年

Answers:


58

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

String s="  $$";
s=s.replaceAll("\\s+\\$\\$","\\$\\$");
//or
//s=s.replaceAll("\\s+\\Q$$\\E","\\$\\$");

$正则表达式的替换参数中的is组符号

所以你需要逃脱它


您能否也解释一下为什么Java将第二个参数视为正则表达式而不是普通字符串?
FranXho

1
它不是将其视为正则表达式。从Matcher.appendReplacement的文档中,“替换字符串可能包含对上一次匹配过程中捕获的子序列的引用:$ {name}或$ g的每次出现都将被评估相应group(name)或group( g)分别...在替换字符串中,可以在其前面加上反斜杠(\ $)作为美元文字($)。”
Matt Sgarlata

关于Matcher.quoteReplacement的提示对于所接受的答案是必不可少的
Daniel Alder

1
为什么在这种情况下也不起作用?pattern = pattern.replaceAll(“ \\ $”,“ \\\\ $”);
Jeevan '18 -10-26

99

String#replaceAll javadoc

请注意,替换字符串中的反斜杠(\)和美元符号($)可能导致结果与被视为文字替换字符串时的结果不同;请参阅Matcher.replaceAll。如果需要,请使用Matcher.quoteReplacement(java.lang.String)取消显示这些字符的特殊含义。

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

String s = "  $$";
s = s.replaceAll("\\s+\\$\\$", Matcher.quoteReplacement("$$"));

也可以使用Pattern#quote来转义模式

String s = "  $$";
s = s.replaceAll("\\s+" + Pattern.quote("$$"), Matcher.quoteReplacement("$$"));

3
由于替换字符串的未知数为99.99_9%,因此此答案的含义要多得多。
AxelH

2
所有这些的问题String.replaceAll(regexp, replacement)并未证明它会将替换String当作幕后的正则表达式处理。作为一名程序员,我可能会对使用regexp进行匹配感兴趣,而对于使用文字进行替换感兴趣-如果API文档中没有相应的提示,我希望这会发生。
Christian Gosch

作为@JonSkeet指出的那样,在JavaDoc的Java SE 6 String,只是没有在第一行。对不起,我的缺点。
Christian Gosch

6

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

$用于引用()匹配的组。因此,您还需要使用反斜杠对其进行转义(并使用第二个反斜杠使Java编译器满意):

String s="  $$";
s = s.replaceAll("\\s+\\$\\$", "\\$\\$");


1
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class HelloWorld{

 public static void main(String []args){
 String msg = "I have %s in my string";

    msg = msg.replaceFirst(Pattern.quote("%s"), Matcher.quoteReplacement("$"));
    System.out.println(msg);
 }

}


0

$ 在替换字符串和正则表达式中都有特殊含义,因此您也必须在其中进行转义:

s=s.replaceAll("\\s+\\$\\$", "\\$\\$");


0

我遇到了同样的问题,所以我最终用split替换了全部。
它为我解决了例外

public static String replaceAll(String source, String key, String value){
    String[] split = source.split(Pattern.quote(key));
    StringBuilder builder = new StringBuilder();
    builder.append(split[0]);
    for (int i = 1; i < split.length; i++) {
        builder.append(value);
        builder.append(split[i]);
    }
    while (source.endsWith(key)) {
        builder.append(value);
        source = source.substring(0, source.length() - key.length());
    }
    return builder.toString();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.