replaceAll(target, replacement)
использует синтаксис регулярного выражения (regex) для target
и частично для replacement
.
Проблема в том, что \
является специальным символом в регулярном выражении (например, \d
представляет цифру) и в литерале строки (например \n
для создания разделителя строк или \"
для представления символа двойной кавычки) , и для создания символа \
нам нужно убрать его с дополнительным \
перед ним на обоих этих уровнях.
Итак, чтобы создать target
регулярное выражение, которое будет представлять символ \
, нам нужно сбежать это дважды:
\\
"\\\\"
(перед каждым \
требуется еще один \
). В случае replacement
\
также является специальным для выхода из другого специального символа, который является $
. Через нотацию $x
часть данных, сопоставляемых регулярным выражением, может быть доступна и повторно использована при замене, например replaceAll("(\d)", "$1$1")
будет дублировать каждую цифру.
Итак, чтобы иметь single \
в replacement
, нам нужен текст, представляющий две обратные косые черты:
\\
\\
, выглядит как "\\\\"
, но поскольку мы хотим заменить на два \
, нам нужно "\\\\\\\\"
там (два "\\\\"
).
replaceAll("\\\\", "\\\\\\\\");
Чтобы облегчить жизнь, Java предоставляет инструменты для автоматического выхода текста в target
и replacement
части. Итак, теперь мы можем сосредоточиться только на строках и забыть о синтаксисе regex:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
, который в нашем случае может выглядеть как
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Или даже проще, если мы не хотите использовать regex, не включает replaceAll
, а вместо этого позволяет использовать replace
(оба метода заменят все target
s, но во втором не будет синтаксис regex). Поэтому вы можете просто написать
theString = theString.replace("\\", "\\\\")