TLDR: usa theString = theString.replace("\\", "\\\\");
invece.
Problema
replaceAll(target, replacement)
usa la sintassi delle espressioni regolari (regex) per target
e parzialmente per replacement
.
Il problema è che \
è un carattere speciale in regex (può essere usato come \d
per rappresentare una cifra) e in String literal (può essere usato come "\n"
per rappresentare il separatore di riga o \"
per sfuggire al simbolo di virgolette doppie che normalmente rappresenterebbe la fine della stringa letterale).
In entrambi questi casi, per creare un \
simbolo possiamo sfuggirgli (renderlo letterale invece di un carattere speciale) inserendo ulteriori \
prima di esso (come se "
usassimo l' escape in stringhe letterali tramite \"
).
Quindi per target
regex che rappresenta il \
simbolo sarà necessario tenere \\
e la stringa letterale che rappresenta tale testo dovrà essere simile "\\\\"
.
Quindi siamo fuggiti \
due volte:
- una volta in regex
\\
- una volta in String literal
"\\\\"
(ognuno \
è rappresentato come "\\"
).
In caso di replacement
\
è anche speciale lì. Ci permette di sfuggire ad altri caratteri speciali $
che, tramite $x
notazione, ci permette di usare parte di dati abbinati da regex e trattenuti catturando il gruppo indicizzato come x
, come "012".replaceAll("(\\d)", "$1$1")
corrisponderà ad ogni cifra, lo $1$1
metterà nel gruppo di cattura 1 e lo sostituirà con le sue due copie (lo duplicherà) risultando in "001122"
.
Quindi, di nuovo, per far replacement
rappresentare il \
letterale dobbiamo evitarlo con addizionale \
che significa che:
- la sostituzione deve contenere due caratteri backslash
\\
- e String letterale che rappresenta
\\
assomiglia a"\\\\"
MA poiché vogliamo replacement
mantenere due backslash avremo bisogno "\\\\\\\\"
(ciascuno \
rappresentato da uno "\\\\"
).
Quindi la versione con replaceAll
può assomigliare
replaceAll("\\\\", "\\\\\\\\");
Modo più semplice
Per rendere la vita più facile, Java fornisce strumenti per eseguire automaticamente l'escape di testo target
e replacement
parti. Quindi ora possiamo concentrarci solo sulle stringhe e dimenticare la sintassi delle espressioni regolari:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
che nel nostro caso può assomigliare
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Anche meglio
Se non abbiamo davvero bisogno del supporto della sintassi regex, non coinvolgiamo replaceAll
affatto. Invece usiamo replace
. Entrambi i metodi sostituiranno tutti target
i messaggi, ma replace
non implicano la sintassi delle espressioni regolari. Quindi potresti semplicemente scrivere
theString = theString.replace("\\", "\\\\");