【问题标题】:String.replaceAll single backslashes with double backslashesString.replaceAll 单反斜杠和双反斜杠
【发布时间】:2010-12-14 16:23:07
【问题描述】:

我正在尝试使用 replaceAllString \something\ 转换为 String \\something\\,但我不断收到各种错误。我认为这是解决方案:

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

但这给出了以下例外:

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

【问题讨论】:

    标签: java escaping backslash replaceall


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        为避免此类麻烦,您可以使用replace(采用纯字符串)代替replaceAll(采用正则表达式)。您仍然需要转义反斜杠,但不是以正则表达式所需的狂野方式。

        【讨论】:

          【解决方案4】:

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

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

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

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

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

          【讨论】:

          • 实际上,它用于应该转换回源代码的 JavaScript AST。您的解决方案有效。谢谢!
          • 如果你仍然想使用String#replaceAll(),你可以用Matcher#quoteReplacement()引用替换字符串:theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
          • Matcher.quoteReplacement( ... ) 是个好方法!请看 Pshemo 的回答!
          【解决方案5】:

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


          问题

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

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

          在这两种情况下,要创建\ 符号,我们可以转义它(使其成为文字而不是特殊字符),方法是在它之前放置额外的\(就像我们在字符串中转义"文字通过\")。

          所以对于代表\ 符号的target 正则表达式将需要保存\\,并且代表此类文本的字符串文字需要看起来像"\\\\"

          所以我们两次逃脱了\

          • 一次在正则表达式\\
          • 在字符串文字"\\\\" 中出现一次(每个\ 表示为"\\")。

          replacement\ 的情况也很特殊。它允许我们转义其他特殊字符$,通过$x 表示法,允许我们使用由正则表达式匹配的部分数据,并由索引为x 的捕获组保存,例如"012".replaceAll("(\\d)", "$1$1") 将匹配每个数字,放置它在捕获组 1 中,$1$1 将用它的两个副本替换它(它会复制它)导致"001122"

          再一次,让replacement 代表\ 文字,我们需要用额外的\ 对其进行转义,这意味着:

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

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

          所以replaceAll 的版本看起来像

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

          更简单的方法

          为了让生活更轻松,Java 提供了自动将文本转义为 targetreplacement 部分的工具。所以现在我们可以只关注字符串,而忘掉正则表达式:

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

          在我们的例子中看起来像

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

          更好

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-02-10
            • 2012-06-16
            • 2013-06-24
            • 1970-01-01
            • 2013-04-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多