String.replace所有单反斜杠和双反斜杠


122

我正在尝试将转换String \something\String \\something\\using replaceAll,但是我不断遇到各种错误。我认为这是解决方案:

theString.replaceAll("\\", "\\\\");

但这给出了以下异常:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1

Answers:


204

将该String#replaceAll()参数解释为正则表达式。该\是转义字符 Stringregex。您需要对正则表达式进行两次转义:

string.replaceAll("\\\\", "\\\\\\\\");

但是您不必为此使用正则表达式,仅是因为您想要逐个字符地进行精确替换,并且这里不需要模式。因此String#replace()就足够了:

string.replace("\\", "\\\\");

更新:根据注释,您似乎想在JavaScript上下文中使用字符串。您最好使用它StringEscapeUtils#escapeEcmaScript()来覆盖更多字符。


实际上,它在应转换回源代码的JavaScript AST中使用。您的解决方案有效。谢谢!
Frank Groeneveld

2
如果String#replaceAll()仍然要使用,则可以使用Matcher#quoteReplacement()引用替换字符串:theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
phse 2015年

Matcher.quoteReplacement(...)是一个好方法!请参阅Pshemo的答案!
Hartmut P.

14

为了避免这种麻烦,您可以使用replace(使用纯字符串)而不是replaceAll(使用正则表达式)。您仍然需要转义反斜杠,但不需要用正则表达式所要求的狂放方式。


10

TLDR:theString = theString.replace("\\", "\\\\");改用。


问题

replaceAll(target, replacement)target部分使用正则表达式(regex)语法replacement

问题是,\正则表达式中的特殊字符(可用于\d表示数字)和字符串文字中的特殊字符(可用于"\n"表示行分隔符或\"转义通常表示字符串文字结尾的双引号。

在这两种情况下,要创建\符号,我们都可以通过在符号前面放置其他字符来对其进行转义(使它成为文字,而不是特殊字符)\(例如",通过来对字符串文字进行转义\")。

因此,target代表\符号的正则表达式将需要按住\\,而代表此类文本的字符串文字则需要看起来像"\\\\"

所以我们逃脱了\两次:

  • 一次在正则表达式中 \\
  • 在String文字中一次"\\\\"(每个\都以表示"\\")。

万一replacement \也很特别。它允许我们转义$通过$x符号的其他特殊字符,允许我们使用与正则表达式匹配并由索引为的捕获组保存的部分数据x,如"012".replaceAll("(\\d)", "$1$1")将匹配每个数字,将其放入捕获组1并将$1$1其替换为两个副本(它将复制它),结果为"001122"

同样,要replacement表示\文字,我们需要使用其他符号对其进行转义,\这意味着:

  • 替换必须包含两个反斜杠字符 \\
  • 和String文字,代表\\看起来像"\\\\"

但是,因为我们要replacement保留两个反斜杠,所以我们需要"\\\\\\\\"(每个反斜杠\代表一个"\\\\")。

所以版本replaceAll可以看起来像

replaceAll("\\\\", "\\\\\\\\");

更简单的方法

做出来的生活更轻松Java提供的工具来自动跳脱文本targetreplacement零件。所以现在我们只关注字符串,而忽略正则表达式语法:

replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))

在我们的情况下看起来像

replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))

更好

如果我们真的不需要正则表达式语法支持,那就不要介入replaceAll。相反,让我们使用replace。两种方法都将替换all target,但是replace不涉及正则表达式语法。所以你可以简单地写

theString = theString.replace("\\", "\\\\");

7

您需要在第一个参数中转义(转义的)反斜杠,因为它是一个正则表达式。替换(第二个参数-参见Matcher#replaceAll(String))也具有反斜杠的特殊含义,因此您必须将其替换为:

theString.replaceAll("\\\\", "\\\\\\\\");

3

是的。正则表达式编译器看到您提供的模式时,只看到一个反斜杠(因为Java的词法分析器已将双重反斜杠变成了一个反斜杠)。您需要替换"\\\\""\\\\",信不信由你!Java确实需要良好的原始字符串语法。

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.