Estou tentando converter o String
\something\
em String
\\something\\
uso replaceAll
, mas continuo recebendo todos os tipos de erros. Eu pensei que esta era a solução:
theString.replaceAll("\\", "\\\\");
Mas isso dá a exceção abaixo:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
fonte
String#replaceAll()
qualquer maneira, pode citar a sequência de substituição com o Matcher # quoteReplacement () :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
Para evitar esse tipo de problema, você pode usar
replace
(que usa uma string simples) em vez dereplaceAll
(que usa uma expressão regular). Você ainda precisará escapar de barras invertidas, mas não das formas selvagens necessárias com expressões regulares.fonte
TLDR: use em
theString = theString.replace("\\", "\\\\");
vez disso.Problema
replaceAll(target, replacement)
usa sintaxe de expressão regular (regex) paratarget
e parcialmente parareplacement
.O problema é que
\
é um caractere especial em regex (pode ser usado como\d
para representar dígito) e em literal de String (pode ser usado como"\n"
para representar separador de linha ou\"
para escapar do símbolo de aspas duplas que normalmente representaria o fim da literal de string).Em ambos os casos, para criar um
\
símbolo, podemos escapá- lo (torná-lo literal em vez de um caractere especial) colocando mais\
antes dele (como escapamos"
em literais de strings via\"
).Portanto, a
target
expressão regular que representa o\
símbolo precisará ser mantida\\
, e a string literal que representa esse texto precisará se parecer"\\\\"
.Então, escapamos
\
duas vezes:\\
"\\\\"
(cada um\
é representado como"\\"
).No caso de
replacement
\
também é especial lá. Ele nos permite escapar de outro caractere especial$
que, por meio de$x
notação, nos permite usar parte dos dados correspondidos por regex e mantidos capturando o grupo indexadox
, como, por exemplo ,"012".replaceAll("(\\d)", "$1$1")
irá corresponder a cada dígito, colocá-lo no grupo de captura 1 e$1$1
substituí-lo por suas duas cópias (duplicará) resultando em"001122"
.Então, novamente, para deixar
replacement
representar\
literal, precisamos escapar dela com mais, o\
que significa que:\\
\\
parece"\\\\"
MAS, como queremos
replacement
manter duas barras invertidas, precisaremos"\\\\\\\\"
(cada uma\
representada por uma"\\\\"
).Então, a versão com
replaceAll
pode parecerManeira mais fácil
Para tornar a vida mais fácil Java fornece ferramentas para escapar automaticamente texto
target
ereplacement
partes. Portanto, agora podemos focar apenas em strings e esquecer a sintaxe regex:que no nosso caso pode parecer
Melhor ainda
Se realmente não precisamos de suporte à sintaxe regex, não vamos envolver
replaceAll
nada. Em vez disso, vamos usarreplace
. Ambos os métodos substituirão todos ostarget
s, masreplace
não envolvem sintaxe regex. Então você poderia simplesmente escreverfonte
Você precisará escapar da barra invertida (escapada) no primeiro argumento, pois é uma expressão regular. Substituição (segundo argumento - consulte Matcher # replaceAll (String) ) também possui um significado especial de barras invertidas; portanto, você precisará substituí-las por:
fonte
Sim ... no momento em que o compilador regex vê o padrão que você deu, ele vê apenas uma barra invertida (desde que o lexer do Java transformou o backwhack duplo em um único). É necessário substituir
"\\\\"
com"\\\\"
, acredite ou não! Java realmente precisa de uma boa sintaxe de cadeia bruta.fonte