TLDR: użyj theString = theString.replace("\\", "\\\\");zamiast tego.
Problem
replaceAll(target, replacement)używa składni wyrażeń regularnych (regex) dla targeti częściowo dla replacement.
Problem polega na tym, że \jest to znak specjalny w wyrażeniu regularnym (może być używany tak jak \ddo reprezentacji cyfry) i w literale String (może być używany jak "\n"do reprezentowania separatora linii lub \"do ucieczki przed symbolem podwójnego cudzysłowu, który normalnie oznaczałby koniec literału ciągu).
W obu tych przypadkach, aby stworzyć \symbol, możemy przed nim uciec (uczynić go dosłownym zamiast znaku specjalnego), umieszczając \przed nim dodatkowe (tak jak "w przypadku literałów ciągu przez \").
Tak więc targetregex reprezentujący \symbol będzie musiał się trzymać \\, a literał łańcuchowy reprezentujący taki tekst będzie musiał wyglądać "\\\\".
Więc uciekliśmy \dwa razy:
- raz w wyrażeniu regularnym
\\
- raz w literale String
"\\\\"(każdy \jest reprezentowany jako "\\").
W przypadku replacement \jest też tam wyjątkowy. Pozwala nam uciec przed innym znakiem specjalnym, $który za pomocą $xnotacji pozwala nam użyć części danych dopasowanych przez wyrażenie regularne i przechowywanych przez grupę przechwytywania indeksowaną tak x, jak "012".replaceAll("(\\d)", "$1$1")będzie pasowała do każdej cyfry, umieści ją w grupie przechwytywania 1 i $1$1zastąpi ją dwoma kopiami (zduplikuje to), w wyniku czego "001122".
Więc znowu, aby replacementreprezentować \dosłownie, musimy uciec od tego dodatkowym, \co oznacza, że:
- zamiennik musi zawierać dwa znaki ukośnika odwrotnego
\\
- i literał String, który reprezentuje
\\wygląd"\\\\"
ALE ponieważ chcemy replacementtrzymać dwa ukośniki odwrotne, których będziemy potrzebować "\\\\\\\\"(każdy \reprezentowany przez jeden "\\\\").
Więc wersja z replaceAllmoże wyglądać
replaceAll("\\\\", "\\\\\\\\");
Łatwiejszy sposób
Aby ułatwić życie, Java udostępnia narzędzia do automatycznego wprowadzania tekstu do targeti replacementczęści. Więc teraz możemy skupić się tylko na łańcuchach i zapomnieć o składni regex:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
co w naszym przypadku może wyglądać
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Nawet lepiej
Jeśli naprawdę nie potrzebujemy obsługi składni wyrażeń regularnych, nie angażujmy się replaceAllw ogóle. Zamiast tego użyjmy replace. Obie metody zastąpią wszystkie target s, ale replacenie obejmują składni wyrażeń regularnych. Możesz więc po prostu napisać
theString = theString.replace("\\", "\\\\");