2015-10-30 7 views
7

Sembra che una stringa contenente i caratteri { o } venga rifiutata durante l'elaborazione di espressioni regolari. Posso capire che questi sono caratteri riservati e ho bisogno di sfuggire loro, quindi se lo faccio:Devo sempre sfuggire ai metacaratteri in una stringa che non è un "letterale"?

string.replaceAll("\\" + pattern); 

Questo funziona, dove pattern è ogni stringa che comincia con {.

Domanda: C'è un modo per evitare tali problemi con stringhe che contengono già tali metacarchi in modo che vengano gestiti automaticamente? Mi sembra che dovrebbe essere lo stesso come l'aggiunta di un doppio apice in una stringa letterale vs accettare una stringa come input che ha già la doppia citazione

+2

usa 'replace' invece di' replaceAll'. – Pshemo

+0

@Pshemo: si comportano in modo diverso? – Jim

+0

Leggi la documentazione ... C'è 'replace (char, char)' e 'replace (String, String)' entrambi dovrebbero funzionare per te. – Pshemo

risposta

4

È possibile utilizzare

java.util.regex.Pattern.quote(java.lang.String) 

per sfuggire caratteri meta utilizzati da regolare espressioni.

8

Uso Pattern.quote(String):

public static String quote(String s) 

Restituisce un modello letterale String per la specificato String.

Questo metodo produce un String che può essere utilizzato per creare un Pattern che corrisponda alla stringa s come se fosse un modello letterale.

I metacaratteri o le sequenze di escape nella sequenza di input non avranno alcun significato speciale.

Parametri:
        s - La stringa da letteralizzato
Returns:
        Una stringa letterale sostituzione
Dal:
        1,5

3

TL; DR

  • se è necessario utilizzare la sintassi regex replaceAll o replaceFirst,
  • se si desidera che il target/replacement coppia di essere trattata come letterali utilizzano replace (sostituisce anche tutti gli eventi del tuo obiettivo).

maggior parte delle persone sono confusi dalla sfortunata denominazione di metodi che sostituiscono in classe String, che sono:

  • replaceAll(String, String)
  • replaceFirst(String, String)
  • replace(CharSequence, CharSequence)
  • replace(char, char)
Metodo

Dal replaceAll afferma esplicitamente che sostituisce tutti obiettivi posible, gente suppone che replace metodo non non garantisce tale comportamento in quanto non contiene All suffisso.
Ma questa ipotesi è errata.

differenza principale tra questi metodi è mostrato in questa tabella:

╔═════════════════════╦═══════════════════════════════════════════════════════════════════╗ 
║      ║        replaced targets      ║ 
║      ╠════════════════════════════════════╦══════════════════════════════╣ 
║      ║   ALL found    ║  ONLY FIRST found  ║ 
╠══════╦══════════════╬════════════════════════════════════╬══════════════════════════════╣ 
║  ║ supported ║ replaceAll(String, String)   ║ replaceFirst(String, String) ║ 
║regex ╠══════════════╬════════════════════════════════════╬══════════════════════════════╣ 
║syntax║  not  ║ replace(CharSequence, CharSequence)║    \/    ║ 
║  ║ supported ║ replace(char, char)    ║    /\    ║ 
╚══════╩══════════════╩════════════════════════════════════╩══════════════════════════════╝ 

Ora, se non avete bisogno di usare regex utilizzare il metodo della sintassi, che non si aspetta, ma si tratta di target e replacement come letterali.

Così, invece di replaceAll(regex, replacement)

uso replace(literal, replacement).


Come potete vedere ci sono due versioni di overload di replace. Entrambi dovrebbero funzionare per te dal momento che non supportano la sintassi regex. La differenza principale tra loro è che:

  • replace(char target, char replacement) crea semplicemente nuova stringa e riempirlo sia con carattere dalla stringa originale, o personaggio che ha deciso in sostituzione (a seconda se è stato pari a bersaglio carattere)

  • replace(CharSequence target, CharSequence replacement) è essenzialmente equivalente replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement.toString()) che significa che è uguale replaceAll ma (che significa che usa internamente motore regex) ma sfugge metacaratteri regex utilizzati in target e replacement per noi automaticamente

+0

@downvoter cura di menzionare cosa c'è di sbagliato in questa risposta in modo da poterla migliorare? – Pshemo

+0

Informazioni utili, quali materiali mi consiglieresti se voglio approfondire la regex di Java? :) – Muhammad

+1

@Muhammad http://www.regular-expressions.info/tutorial.html è il miglior tutorial che ho trovato finora sulla regex pura e la maggior parte dei suoi sapori implementati in diverse lingue. Anche il tutorial sulla regex di Java è bello https://docs.oracle.com/javase/tutorial/essential/regex/ ma dovresti anche leggere la documentazione della classe Pattern https://docs.oracle.com/javase/8/docs/api /java/util/regex/Pattern.html che contiene molte informazioni su quali meccanismi di regex sono supportati in Java. – Pshemo

0

non hai bisogno di alcun codice aggiuntivo, solo i \Q e \E costrutti, come documentato in Java's Pattern class.

Ad esempio, nel codice seguente:

String foobar = "crazyPassword=f()[email protected]{}+"; 
Pattern regex = Pattern.compile("\\Q" + foobar "\\E"); 

modello sarebbe compilare e caratteri speciali di foobar non verrebbe interpretato come caratteri espressioni regolari. Vedi demo here.

L'unica cosa che non corrisponde è dove l'input contiene un valore letterale \E. Se hai bisogno di risolvere anche questo problema, fammelo sapere in un commento e modificherò per aggiungerlo.

Problemi correlati