Domanda

Sto cercando di convertire la String \something\ nella String \\something\\ utilizzando replaceAll, ma io continuo a ricevere tutti i tipi di errori. Ho pensato che questa era la soluzione:

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

Ma questo dà l'eccezione di seguito:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
È stato utile?

Soluzione

Il String#replaceAll() interpreta l'argomento come un espressioni regolari . Il \ è un carattere di escape in sia e String regex. È necessario fare doppio fuggire per regex:

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

Ma non hanno necessariamente bisogno regex per questo, semplicemente perché si vuole un esatto sostituzione di un carattere per carattere e non hai bisogno di modelli qui. Quindi, String#replace() dovrebbe essere sufficiente:

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

Aggiorna : come per i commenti, in cui sembra voler utilizzare la stringa in un contesto JavaScript. È forse meglio usereste StringEscapeUtils#escapeEcmaScript() invece di coprire più caratteri.

Altri suggerimenti

Per evitare questo tipo di problemi, è possibile utilizzare replace (che prende una stringa normale) al posto di replaceAll (che prende un'espressione regolare). Sarà comunque necessario per sfuggire backslash, ma non nei modi selvatici richiesti con le espressioni regolari.

TLDR:. Uso theString = theString.replace("\\", "\\\\"); invece


Problema

replaceAll(target, replacement) utilizza la sintassi delle espressioni regolari (regex) per target e parzialmente per replacement.

Il problema è che \ è carattere speciale regex (che può essere utilizzato come \d per rappresenta cifre) e String letterale (può essere utilizzato come "\n" per rappresentare separatore di linea o \" sfuggire simbolo doppia preventivo che normalmente rappresenterebbe fine di stringa letterale).

In entrambi i casi, per creare il simbolo \ possiamo Escape è (renderlo letteralmente invece di carattere speciale), ponendo ulteriore \ prima che (come noi fuggiamo " in stringhe letterali via \").

Quindi, per target regex che rappresenta il simbolo \ dovrà tenere \\, e stringa letterale che rappresenta tale testo dovrà assomigliare "\\\\".

Così siamo fuggiti \ due volte:

  • una volta nella \\ regex
  • una volta nella stringa "\\\\" letterale (ogni \ è rappresentato come "\\").

In caso di replacement \ è anche speciale. Esso permette di sfuggire altro $ carattere speciale che tramite la notazione $x, ci permette di utilizzare porzione di dati appaiati per regex e posseduti dal gruppo catturando indicizzati come x, come "012".replaceAll("(\\d)", "$1$1") corrisponderà ogni cifra, collocarlo nel catturare gruppo 1 e $1$1 sostituirà con i suoi due copie (sarà duplicarlo) con conseguente "001122".

Quindi, di nuovo, di lasciare replacement rappresentano \ letterale abbiamo bisogno di fuggire con ulteriore \ che significa che:

  • sostituzione deve contenere due barre rovesciate \\
  • e stringa letterale che rappresenta \\ sembra "\\\\"

Ma dal momento che vogliamo replacement di tenere due backslash avremo bisogno "\\\\\\\\" (ogni \ rappresentato da uno "\\\\").

Quindi, la versione con replaceAll può apparire come

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

modo più facile

Per rendere la vita più facile uscire Java fornisce gli strumenti per sfuggire automaticamente il testo in target e replacement parti. Così ora siamo in grado di concentrarsi solo sulle stringhe, e dimenticare la sintassi regex:

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

che nel nostro caso può apparire come

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

Ancora meglio

Se non abbiamo davvero bisogno di sostegno sintassi regex consente di non coinvolgere replaceAll a tutti. Invece lascia uso replace. Entrambi i metodi sostituiranno tutti targets, ma replace non comporta la sintassi regex. Così si potrebbe semplicemente scrivere

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

Avrete bisogno di sfuggire alla (sfuggito) backslash nel primo argomento in quanto è un'espressione regolare. Sostituzione (2 ° argomento - vedere Matcher # replaceAll (String) ) ha anche il significato particolare di backslash, quindi dovrete per sostituire quelli a:

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

Si ... per il momento il compilatore regex vede il modello che hai dato, esso vede solo una singola barra rovesciata (dal lexer di Java ha trasformato il doppio backwhack in una sola). È necessario sostituire "\\\\" con "\\\\", che ci crediate o no! Java davvero bisogno di una buona sintassi della stringa crudo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top