String.replaceAll单反斜杠,带双反斜杠

时间:2009-11-09 15:40:55

标签: java escaping backslash replaceall

我正在尝试使用String\something\ String转换为\\something\\ replaceAll,但我一直遇到各种错误。我认为这是解决方案:

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

但是这给出了以下例外:

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

5 个答案:

答案 0 :(得分:185)

String#replaceAll()将参数解释为regular expression\ Stringregex中的转义字符。你需要为正则表达式双重转义:

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

但是你不一定需要正则表达式,因为你想要一个确切的逐字符替换,你不需要这里的模式。所以String#replace()就足够了:

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

更新:根据评论,您似乎想要在JavaScript上下文中使用该字符串。您可能最好使用StringEscapeUtils#escapeEcmaScript()来覆盖更多字符。

答案 1 :(得分:14)

为了避免这种麻烦,您可以使用replace(采用普通字符串)而不是replaceAll(采用正则表达式)。你仍然需要逃避反斜杠,但不能用正则表达式所需的狂野方式。

答案 2 :(得分:8)

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

问题

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

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

在这两种情况下,为了创建\符号,我们可以转义(通过在其前面放置额外的\来使其成为文字而非特殊字符)(就像我们转义{通过")在字符串文字中{1}}。

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

所以我们两次转发"\\\\"

  • 一次使用正则表达式\
  • 一次使用字符串文字\\(每个"\\\\"表示为\)。

如果"\\" replacement在那里也很特别。它允许我们通过\表示法转义其他特殊字符$,允许我们使用正则表达式匹配的数据部分,并通过捕获被编入$x的组来保存,如x }将匹配每个数字,将其置于捕获组1中,"012".replaceAll("(\\d)", "$1$1")将其替换为两个副本(它将复制它),从而生成$1$1

再次,让"001122"代表replacement字面值,我们需要使用额外的\来转义它,这意味着:

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

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

"\\\\"的版本看起来像

replaceAll

更轻松的方式

为了让生活更轻松,Java提供了自动将文本转义为replaceAll("\\\\", "\\\\\\\\"); target部分的工具。所以现在我们只关注字符串,忘记正则表达式语法:

replacement

在我们的案例中可能看起来像

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

更好

如果我们真的不需要正则表达式语法支持,则根本不要涉及replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\")) 。而是让我们使用replaceAll。这两种方法都将取代 所有 replace,但target不涉及正则表达式语法。所以你可以简单地写

replace

答案 3 :(得分:7)

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

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

答案 4 :(得分:4)

是的......当正则表达式编译器看到你给出它的模式时,它只看到一个反斜杠(因为Java的词法分析器已经将双重后退变成了单个反斜杠)。无论信不信,您需要将"\\\\"替换为"\\\\"! Java确实需要一个很好的原始字符串语法。