J'essaie de convertir le String
\something\
dans le String
\\something\\
en utilisant replaceAll
, mais je continue à avoir toutes sortes d’erreurs. Je pensais que c'était la solution:
theString.replaceAll("\\", "\\\\");
Mais cela donne l'exception ci-dessous:
Java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
Le String#replaceAll()
interprète l'argument comme un expression régulière . Le \
Est un caractère d'échappement entre et les deux String
et regex
. Vous devez double-y échapper pour regex:
string.replaceAll("\\\\", "\\\\\\\\");
Mais vous n’avez pas nécessairement besoin de regex pour cela, simplement parce que vous voulez un remplacement exact caractère par caractère et que vous n’avez pas besoin de motifs ici. Donc String#replace()
devrait suffire:
string.replace("\\", "\\\\");
Update : selon les commentaires, vous semblez vouloir utiliser la chaîne dans un contexte JavaScript. Vous feriez peut-être mieux d'utiliser StringEscapeUtils#escapeEcmaScript()
pour couvrir plus de caractères.
Pour éviter ce genre de problème, vous pouvez utiliser replace
(qui prend une chaîne simple) au lieu de replaceAll
(qui prend une expression régulière). Vous aurez toujours besoin d'échapper aux barres obliques inverses, mais pas de la manière sauvage requise avec les expressions régulières.
TLDR: utilisez theString = theString.replace("\\", "\\\\");
à la place.
replaceAll(target, replacement)
utilise la syntaxe d'expression régulière (regex) pour target
et partiellement pour replacement
.
Le problème est que \
est un caractère spécial dans regex (il peut être utilisé comme \d
pour représenter digit) et en littéral chaîne (il peut être utilisé comme "\n"
pour représenter un séparateur de ligne ou \"
pour échapper au symbole de guillemet double qui représenterait normalement la fin de chaîne littérale. ).
Dans les deux cas, pour créer le symbole \
, nous pouvons l'échapper le (le rendre littéral au lieu d'un caractère spécial) en plaçant un \
supplémentaire devant celui-ci (comme nous échappons le "
dans les littéraux de chaîne via \"
).
Donc, pour target
regex représentant le symbole \
devra contenir \\
, et la chaîne de caractères représentant ce texte devra ressembler à "\\\\"
.
Nous avons donc échappé deux fois à \
:
\\
"\\\\"
(chaque \
est représenté par "\\"
).Dans le cas de replacement
\
est également spécial. Il nous permet d’échapper à un autre caractère spécial $
qui, via la notation $x
, nous permet d’utiliser une partie des données mises en correspondance par regex et conservées par un groupe de capture indexé sous la forme x
, comme "012".replaceAll("(\\d)", "$1$1")
, correspondant à chaque digit, placez-le dans le groupe de capture 1 et $1$1
le remplacera par ses deux copies (il le dupliquera), résultant en "001122"
.
Encore une fois, pour que replacement
représente \
littéral, nous devons y échapper avec un \
supplémentaire, ce qui signifie que:
\\
\\
ressemble à "\\\\"
MAIS puisque nous voulons que replacement
tienne deux barres obliques inverses, nous avons besoin de "\\\\\\\\"
(chaque \
représenté par un "\\\\"
).
Donc, la version avec replaceAll
peut ressembler à
replaceAll("\\\\", "\\\\\\\\");
Pour rendre la vie plus facile Java fournit des outils pour échapper automatiquement du texte dans les parties target
et replacement
. Nous pouvons maintenant nous concentrer uniquement sur les chaînes et oublier à propos de la syntaxe des expressions rationnelles:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
qui dans notre cas peut ressembler à
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Si nous n’avons pas vraiment besoin du support de la syntaxe regex, n'impliquons pas du tout replaceAll
. À la place, utilisons replace
. Les deux méthodes remplaceront all target
s, mais replace
ne comporte pas syntaxe de regex. Pour que vous puissiez simplement écrire
theString = theString.replace("\\", "\\\\");
Vous aurez besoin d'échapper à la barre oblique inverse (échappée) dans le premier argument car il s'agit d'une expression régulière. Remplacement (2ème argument - voir Matcher # replaceAll (String) ) a également sa signification particulière de barres obliques inverses. Vous devrez donc remplacer celles-ci par:
theString.replaceAll("\\\\", "\\\\\\\\");
Oui ... au moment où le compilateur regex voit le motif que vous lui avez donné, il ne voit plus qu'une seule barre oblique inverse (car le lexer de Java a transformé le double backwhack en un seul). Vous devez remplacer "\\\\"
avec "\\\\"
, Croyez-le ou non! Java a vraiment besoin d'une bonne syntaxe de chaîne brute.