String.replaceTodos os backslashes únicos com barras invertidas duplas

Eu estou tentando converter o String \something\ para o String \\something\\ usando replaceAll , mas continuo recebendo todos os tipos de erros. Eu pensei que esta era a solução:

 theString.replaceAll("\\", "\\\\"); 

Mas isso dá a seguinte exceção:

 java.util.regex.PatternSyntaxException: Unexpected internal error near index 1 

O String#replaceAll() interpreta o argumento como uma expressão regular . O \ é um caractere de escape em String e regex . Você precisa duplicá-lo para regex:

 string.replaceAll("\\\\", "\\\\\\\\"); 

Mas você não precisa necessariamente de regex para isso, simplesmente porque deseja uma substituição exata de caractere por caractere e não precisa de padrões aqui. Então String#replace() deve ser suficiente:

 string.replace("\\", "\\\\"); 

Atualização : de acordo com os comentários, você parece querer usar a string no contexto JavaScript. Talvez seja melhor usar StringEscapeUtils#escapeEcmaScript() para cobrir mais caracteres.

Para evitar esse tipo de problema, você pode usar replace (que recebe uma string simples) em vez de replaceAll (que recebe uma expressão regular). Você ainda precisará escaping das barras invertidas, mas não das formas selvagens exigidas com expressões regulares.

Você precisará escaping da barra invertida (escapada) no primeiro argumento, pois é uma expressão regular. Substituição (segundo argumento – veja Matcher # replaceAll (String) ) também tem seu significado especial de barras invertidas, então você terá que substituí-las por:

 theString.replaceAll("\\\\", "\\\\\\\\"); 

replaceAll(target, replacement) usa a syntax de expressão regular (regex) para target e parcialmente para replacement .

O problema é que \ é um caracter especial em regex (como \d representa dígito) e em literal de string (como \n para criar separador de linha ou \" para representar o símbolo de aspas duplas), e para criar \ símbolo precisamos escaping dele adicional \ antes em ambos os níveis.

Então, para criar target regex target que represente \ símbolo, precisamos escaping dele duas vezes:

  • em regex \\
  • String literal "\\\\" (cada \ precisa do seu próprio extra \ antes).

Em caso de replacement \ também é especial para escaping de um outro caracter especial que é $ . Por meio da notação $x , a parte dos dados correspondidos pelo regex pode ser acessada e reutilizada em substituição, como replaceAll("(\d)", "$1$1") duplicará cada dígito.

Então, novamente, para ter replacement única , precisamos de texto representando duas barras invertidas:

  • \\
  • mas string literal representando \\ parecido com "\\\\"

MAS, como queremos colocar dois em substituição, precisamos de "\\\\\\\\"

 replaceAll("\\\\", "\\\\\\\\"); 

Para facilitar a vida, o Java fornece ferramentas para automaticamente enviar texto para target peças de target e de replacement . Então, agora podemos nos concentrar apenas em strings e esquecer a syntax de regex:

 replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement)) 

que no nosso caso pode parecer

 replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\")) 

Ou ainda mais simples, se não quisermos usar o regex, não vamos envolver replaceAll e, em vez disso, vamos usar replace (ambos os methods replaceão todos target s do target , mas o segundo não envolve a syntax do regex). Então você poderia simplesmente escrever

 theString = theString.replace("\\", "\\\\") 

Sim … no momento em que o compilador regex vê o padrão que você deu, ele vê apenas uma única barra invertida (desde que o léxico do Java transformou o backwhack duplo em um único). Você precisa replace "\\\\" por "\\\\" , acredite ou não! Java realmente precisa de uma boa syntax de string raw.

    Intereting Posts