我正在尝试使用String
将\something\
String
转换为\\something\\
replaceAll
,但我一直遇到各种错误。我认为这是解决方案:
theString.replaceAll("\\", "\\\\");
但是这给出了以下例外:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
答案 0 :(得分:185)
String#replaceAll()
将参数解释为regular expression。 \
是 String
和regex
中的转义字符。你需要为正则表达式双重转义:
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确实需要一个很好的原始字符串语法。