我尝试使用replaceAll将String\something\转换为String\\something\\,但我不断收到各种错误。我认为这是解决方案:
replaceAll
String
\something\
\\something\\
theString.replaceAll("\\", "\\\\");
但这给出了以下例外情况:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
s1ag04yj1#
String#replaceAll()将参数解释为正则表达式。\在**String和regex中都是转义字符。对于regex,需要对其进行双转义:
String#replaceAll()
\
regex
string.replaceAll("\\\\", "\\\\\\\\");
但是你不一定需要正则表达式,因为你想要一个字符一个字符地替换,这里你不需要模式,所以String#replace()就足够了:
String#replace()
string.replace("\\", "\\\\");
更新:根据评论,你似乎想在JavaScript上下文中使用这个字符串。你可能更好地使用StringEscapeUtils#escapeEcmaScript()来覆盖更多的字符。
StringEscapeUtils#escapeEcmaScript()
vh0rcniy2#
TLDR:使用theString = theString.replace("\\", "\\\\");代替。
theString = theString.replace("\\", "\\\\");
replaceAll(target, replacement)将正则表达式(regex)语法用于target,部分用于replacement。问题是\是正则表达式中的特殊字符(它可以像\d一样用于表示数字)和字符串文字中的特殊字符(它可以像"\n"一样用于表示行分隔符或\"一样用于转义通常表示字符串文字结尾的双引号符号)。在这两种情况下,要创建\符号,我们都可以通过在它前面放置额外的\来 * 转义 * 它(使它成为文本而不是特殊字符)(就像我们通过\"转义字符串文本中的"一样)。所以对于target,表示\符号的正则表达式需要包含\\,表示此类文本的字符串文字需要看起来像"\\\\"。所以我们逃脱了\两次:
replaceAll(target, replacement)
target
replacement
\d
"\n"
\"
"
\\
"\\\\"
"\\"
在replacement的情况下,\在那里也是特殊的。它允许我们转义其他特殊字符$,通过$x表示法,允许我们使用由regex匹配的数据部分,并由索引为x的捕获组保存,如"012".replaceAll("(\\d)", "$1$1")将匹配每个数字,将其放入捕获组1中,$1$1将用其两个副本替换它(将复制它),生成"001122"。同样,要让replacement表示\字面量,我们需要使用额外的\对其进行转义,这意味着:
$
$x
x
"012".replaceAll("(\\d)", "$1$1")
$1$1
"001122"
但是,由于我们希望replacement包含 * 两个 * 反斜杠,因此我们将需要"\\\\\\\\"(每个\由一个"\\\\"表示)。因此,replaceAll版本可能如下所示
"\\\\\\\\"
replaceAll("\\\\", "\\\\\\\\");
为了让事情变得更简单,Java提供了一些工具来自动将文本转义为target和replacement部分,所以现在我们可以只关注字符串,而忽略正则表达式语法:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
在我们的例子中看起来像
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
replace
如果我们真的不需要正则表达式语法支持,我们就不需要用到replaceAll,而是用replace,这两个方法都会替换***all***target,但是replace不需要正则表达式语法,所以你可以简单地写
llycmphe3#
为了避免这类麻烦,可以使用replace(接受普通字符串)代替replaceAll(接受正则表达式),但仍然需要转义反斜杠,但不是正则表达式所要求的那种任意转义方式。
llmtgqce4#
你需要转义第一个参数中的反斜杠,因为它是一个正则表达式。替换(第二个参数-参见Matcher#replaceAll(String))也有反斜杠的特殊含义,所以你需要替换它们:
theString.replaceAll("\\\\", "\\\\\\\\");
dw1jzc5e5#
是的......当regex编译器看到你给它的模式时,它只看到了一个反斜杠(因为Java的lexer已经把两个反斜杠变成了一个)。你需要用"\\\\"替换"\\\\",信不信由你!Java真的需要一个好的原始字符串语法。
5条答案
按热度按时间s1ag04yj1#
String#replaceAll()
将参数解释为正则表达式。\
在**String
和regex
中都是转义字符。对于regex,需要对其进行双转义:但是你不一定需要正则表达式,因为你想要一个字符一个字符地替换,这里你不需要模式,所以
String#replace()
就足够了:更新:根据评论,你似乎想在JavaScript上下文中使用这个字符串。你可能更好地使用
StringEscapeUtils#escapeEcmaScript()
来覆盖更多的字符。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
更简单为了让事情变得更简单,Java提供了一些工具来自动将文本转义为
target
和replacement
部分,所以现在我们可以只关注字符串,而忽略正则表达式语法:在我们的例子中看起来像
甚至更好:使用
replace
如果我们真的不需要正则表达式语法支持,我们就不需要用到
replaceAll
,而是用replace
,这两个方法都会替换***all***target
,但是replace
不需要正则表达式语法,所以你可以简单地写llycmphe3#
为了避免这类麻烦,可以使用
replace
(接受普通字符串)代替replaceAll
(接受正则表达式),但仍然需要转义反斜杠,但不是正则表达式所要求的那种任意转义方式。llmtgqce4#
你需要转义第一个参数中的反斜杠,因为它是一个正则表达式。替换(第二个参数-参见Matcher#replaceAll(String))也有反斜杠的特殊含义,所以你需要替换它们:
dw1jzc5e5#
是的......当regex编译器看到你给它的模式时,它只看到了一个反斜杠(因为Java的lexer已经把两个反斜杠变成了一个)。你需要用
"\\\\"
替换"\\\\"
,信不信由你!Java真的需要一个好的原始字符串语法。