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("\\", "\\\\");