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