Pergunta

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

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

Mas isso dá a exceção abaixo:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
Foi útil?

Solução

o String#replaceAll() interpreta o argumento como um expressão regular. o \ é um personagem de fuga em Ambas String e regex. Você precisa dobrar duas vezes para regex:

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

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

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

Atualizar: De acordo com os comentários, você parece querer usar a string no contexto JavaScript. Talvez seja melhor usar StringEscapeUtils#escapeEcmaScript() Em vez disso, para cobrir mais personagens.

Outras dicas

Para evitar esse tipo de problema, você pode usar replace (que leva uma corda simples) em vez de replaceAll (que leva uma expressão regular). Você ainda precisará escapar de barras -barras, mas não das maneiras selvagens necessárias com expressões regulares.

TLDR: Use theString = theString.replace("\\", "\\\\"); em vez de.


Problema

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

O problema é isso \ é um personagem especial em regex (pode ser usado como \d para representa o dígito) e em literais de corda (pode ser usado como "\n" Para representar o separador de linha ou \" para escapar do símbolo de citação dupla que normalmente representaria o final da string literal).

Em ambos os casos para criar \ Símbolo que podemos escapar (tornar -o literal em vez de caráter especial) colocando \ antes disso (como nós escapamos " em literais de cordas via \").

Então para target regex representando \ Símbolo precisará segurar \\, e a literal de cordas que representam esse texto precisarão parecer "\\\\".

Então nós escapamos \ duas vezes:

  • uma vez em regex \\
  • uma vez em string literal "\\\\" (cada \ é representado como "\\").

No caso de replacement \ também é especial lá. Nos permite escapar de outro personagem especial $ Qual via $x notação, nos permite usar a parte dos dados correspondidos por Regex e mantidos capturando o grupo indexado como x, Curti "012".replaceAll("(\\d)", "$1$1") combinará cada dígito, coloque -o na captura do Grupo 1 e $1$1 o substituirá por suas duas cópias (ele duplicará) resultando em "001122".

Então, novamente, para deixar replacement representar \ literal, precisamos escapar disso com adicional \ o que significa que:

  • A substituição deve conter dois caracteres de barragem \\
  • e literal de cordas que representa \\ parece "\\\\"

Mas desde que queremos replacement segurar dois barras de barriga que precisaremos "\\\\\\\\" (cada \ representado por um "\\\\").

Então versão com replaceAll pode parecer assim

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

Maneira mais fácil

Para entender a vida mais fácil, o Java fornece ferramentas para escapar automaticamente no texto em target e replacement peças. Então agora podemos nos concentrar apenas em strings e esquecer a sintaxe regex:

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

Qual no nosso caso pode parecer

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

Melhor ainda

Se realmente não precisamos de suporte de sintaxe da regex, não envolva replaceAll de forma alguma. Em vez disso, vamos usar replace. Ambos os métodos substituirão tudo targets, mas replace Não envolve sintaxe regex. Então você pode simplesmente escrever

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

Você precisará escapar da barra de barriga (escapada) no primeiro argumento, pois é uma expressão regular. Substituição (2º argumento - ver Matcher#replaceall (string)) também tem seu significado especial de barris, então você terá que substituí -las para:

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

Sim ... quando o compilador Regex vê o padrão que você deu, ele vê apenas uma única barra de barra (já que o Lexer de Java transformou o backwhack duplo em um único). Você precisa substituir "\\\\" com "\\\\", Acredite ou não! O Java realmente precisa de uma boa sintaxe de cordas cruas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top