java 字符串.replaceAll单反斜杠与双反斜杠

ljsrvy3e  于 2023-01-01  发布在  Java
关注(0)|答案(5)|浏览(427)

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

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

但这给出了以下例外情况:

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

s1ag04yj1#

String#replaceAll()将参数解释为正则表达式。\在**Stringregex中都是转义字符。对于regex,需要对其进行双转义:

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

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

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

更新:根据评论,你似乎想在JavaScript上下文中使用这个字符串。你可能更好地使用StringEscapeUtils#escapeEcmaScript()来覆盖更多的字符。

vh0rcniy

vh0rcniy2#

TLDR:使用theString = theString.replace("\\", "\\\\");代替。

问题

replaceAll(target, replacement)将正则表达式(regex)语法用于target,部分用于replacement
问题是\是正则表达式中的特殊字符(它可以像\d一样用于表示数字)和字符串文字中的特殊字符(它可以像"\n"一样用于表示行分隔符或\"一样用于转义通常表示字符串文字结尾的双引号符号)。
在这两种情况下,要创建\符号,我们都可以通过在它前面放置额外的\来 * 转义 * 它(使它成为文本而不是特殊字符)(就像我们通过\"转义字符串文本中的"一样)。
所以对于target,表示\符号的正则表达式需要包含\\,表示此类文本的字符串文字需要看起来像"\\\\"
所以我们逃脱了\两次:

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

replacement的情况下,\在那里也是特殊的。它允许我们转义其他特殊字符$,通过$x表示法,允许我们使用由regex匹配的数据部分,并由索引为x的捕获组保存,如"012".replaceAll("(\\d)", "$1$1")将匹配每个数字,将其放入捕获组1中,$1$1将用其两个副本替换它(将复制它),生成"001122"
同样,要让replacement表示\字面量,我们需要使用额外的\对其进行转义,这意味着:

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

但是,由于我们希望replacement包含 * 两个 * 反斜杠,因此我们将需要"\\\\\\\\"(每个\由一个"\\\\"表示)。
因此,replaceAll版本可能如下所示

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

使用replaceAll更简单

为了让事情变得更简单,Java提供了一些工具来自动将文本转义为targetreplacement部分,所以现在我们可以只关注字符串,而忽略正则表达式语法:

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

在我们的例子中看起来像

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

甚至更好:使用replace

如果我们真的不需要正则表达式语法支持,我们就不需要用到replaceAll,而是用replace,这两个方法都会替换***all***target,但是replace不需要正则表达式语法,所以你可以简单地写

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

llycmphe3#

为了避免这类麻烦,可以使用replace(接受普通字符串)代替replaceAll(接受正则表达式),但仍然需要转义反斜杠,但不是正则表达式所要求的那种任意转义方式。

llmtgqce

llmtgqce4#

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

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

dw1jzc5e5#

是的......当regex编译器看到你给它的模式时,它只看到了一个反斜杠(因为Java的lexer已经把两个反斜杠变成了一个)。你需要用"\\\\"替换"\\\\",信不信由你!Java真的需要一个好的原始字符串语法。

相关问题