Guida ai caratteri di escape nelle espressioni regolari Java

1. Panoramica

L'API delle espressioni regolari in Java, java.util.regex , è ampiamente utilizzata per la corrispondenza dei modelli. Per saperne di più, puoi seguire questo articolo.

In questo articolo, ci concentreremo sull'escape dei caratteri con un'espressione regolare e mostreremo come può essere fatto in Java.

2. Caratteri RegExp speciali

Secondo la documentazione dell'API delle espressioni regolari Java, esiste una serie di caratteri speciali noti anche come metacaratteri presenti in un'espressione regolare.

Quando vogliamo consentire ai personaggi come sono invece di interpretarli con i loro significati speciali, dobbiamo sfuggirli. Eseguendo l'escape di questi caratteri, li costringiamo a essere trattati come caratteri normali quando si confronta una stringa con una data espressione regolare.

I metacaratteri da cui di solito abbiamo bisogno di sfuggire in questo modo sono:

Diamo un'occhiata a un semplice esempio di codice in cui abbiniamo una stringa di input con un modello espresso in un'espressione regolare.

Questo test mostra che per una data stringa di input foof quando il pattern foo . ( foo che termina con un punto) viene trovato, restituisce un valore true che indica che la corrispondenza ha successo.

@Test public void givenRegexWithDot_whenMatchingStr_thenMatches() { String strInput = "foof"; String strRegex = "foo."; assertEquals(true, strInput.matches(strRegex)); }

Potresti chiederti perché la corrispondenza ha esito positivo quando non è presente alcun punto (.) Nella stringa di input ?

La risposta è semplice. Il punto (.) È un metacarattere: il significato speciale del punto qui è che può esserci "qualsiasi carattere" al suo posto. Pertanto, è chiaro come il matcher abbia determinato che viene trovata una corrispondenza.

Diciamo che non vogliamo trattare il carattere punto (.) Con il suo significato unico. Invece, vogliamo che venga interpretato come un segno di punto. Ciò significa che nell'esempio precedente, non vogliamo lasciare che il pattern foo. per avere una corrispondenza nella stringa di input .

Come gestiremmo una situazione come questa? La risposta è: dobbiamo sfuggire al carattere punto (.) In modo che il suo significato speciale venga ignorato.

Analizziamolo più in dettaglio nella prossima sezione.

3. Caratteri in fuga

Secondo la documentazione dell'API Java per le espressioni regolari, ci sono due modi in cui possiamo eseguire l'escape di caratteri che hanno un significato speciale. In altre parole, per costringerli a essere trattati come caratteri normali.

Vediamo cosa sono:

  1. Precedere un metacarattere con una barra rovesciata (\)
  2. Racchiudi un metacarattere con \ Q e \ E

Questo significa semplicemente che nell'esempio che abbiamo visto prima, se vogliamo sfuggire al carattere punto, dobbiamo mettere un carattere barra rovesciata prima del carattere punto. In alternativa, possiamo inserire il carattere punto tra \ Q e \ E.

3.1. Escaping utilizzando la barra rovesciata

Questa è una delle tecniche che possiamo usare per eseguire l'escape dei metacaratteri in un'espressione regolare. Tuttavia, sappiamo che il carattere barra rovesciata è anche un carattere di escape nei valori letterali Java String . Pertanto, è necessario raddoppiare il carattere barra rovesciata quando lo si utilizza per precedere qualsiasi carattere (incluso il carattere \ stesso).

Quindi nel nostro esempio, dobbiamo cambiare l'espressione regolare come mostrato in questo test:

@Test public void givenRegexWithDotEsc_whenMatchingStr_thenNotMatching() { String strInput = "foof"; String strRegex = "foo\\."; assertEquals(false, strInput.matches(strRegex)); }

Qui, il carattere del punto viene sottoposto a escape, quindi il matcher lo tratta semplicemente come un punto e cerca di trovare un modello che termini con il punto (cioè pippo ).

In questo caso, restituisce false poiché non esiste alcuna corrispondenza nella stringa di input per quel modello.

3.2. Escaping utilizzando \ Q & \ E

In alternativa, possiamo usare \ Q e \ E per eseguire l'escape del carattere speciale. \ Q indica che tutti i caratteri fino a \ E deve essere sfuggito e \ E significa che dobbiamo porre fine alla fuga che è stato avviato con \ Q .

Ciò significa solo che qualsiasi cosa si trovi tra \ Q e \ E verrebbe sottoposta a escape.

Nel test mostrato qui, la split () della classe String fa una corrispondenza usando l'espressione regolare fornita.

Il nostro requisito è dividere la stringa di input dal carattere pipe (|) in parole. Pertanto, utilizziamo un modello di espressione regolare per farlo.

Il carattere pipe è un metacarattere di cui è necessario eseguire l'escape nell'espressione regolare.

Qui, l'escape viene eseguito inserendo il carattere pipe tra \ Q e \ E :

@Test public void givenRegexWithPipeEscaped_whenSplitStr_thenSplits() \\E"; assertEquals(4, strInput.split(strRegex).length); 

4. Il metodo Pattern.quote (String S)

Il metodo Pattern.Quote (String S) nella classe java.util.regex.Pattern converte un determinato pattern di espressione regolare String in un pattern String letterale . Ciò significa che tutti i metacaratteri nella stringa di input vengono trattati come caratteri normali.

L'uso di questo metodo sarebbe un'alternativa più conveniente rispetto all'uso di \ Q & \ E poiché avvolge la stringa data con loro.

Vediamo questo metodo in azione:

@Test public void givenRegexWithPipeEscQuoteMeth_whenSplitStr_thenSplits() bar

In questo rapido test, il metodo Pattern.quote () viene utilizzato per sfuggire al modello regex dato e trasformarlo in un letterale String . In altre parole, sfugge a tutti i metacaratteri presenti nel pattern regex per noi. Si sta facendo un lavoro simile a \ Q & \ E .

Il carattere pipe è sottoposto a escape dal metodo Pattern.quote () e split () lo interpreta come un letterale String per il quale divide l'input.

Come possiamo vedere, questo è un approccio molto più pulito e anche gli sviluppatori non devono ricordare tutte le sequenze di fuga.

Dobbiamo notare che Pattern.quote racchiude l'intero blocco con una singola sequenza di escape. Se volessimo eseguire l'escape dei caratteri individualmente, avremmo bisogno di utilizzare un algoritmo di sostituzione del token.

5. Esempi aggiuntivi

Diamo un'occhiata a come funziona il metodo replaceAll () di java.util.regex.Matcher .

Se abbiamo bisogno di sostituire tutte le occorrenze di un dato carattere String con un altro, possiamo usare questo metodo passandogli un'espressione regolare.

Immagina di avere un input con più occorrenze del carattere $ . Il risultato che vogliamo ottenere è la stessa stringa con il carattere $ sostituito da £.

Questo test dimostra come il pattern $ viene passato senza essere sottoposto a escape:

@Test public void givenRegexWithDollar_whenReplacing_thenNotReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertThat(output, not(equalTo(m.replaceAll(strReplacement)))); }

Il test afferma che $ non è stato sostituito correttamente da £ .

Ora, se sfuggiamo al pattern regex, la sostituzione avviene correttamente e il test passa come mostrato in questo frammento di codice:

@Test public void givenRegexWithDollarEsc_whenReplacing_thenReplace() { String strInput = "I gave $50 to my brother." + "He bought candy for $35. Now he has $15 left."; String strRegex = "\\$"; String strReplacement = "£"; String output = "I gave £50 to my brother." + "He bought candy for £35. Now he has £15 left."; Pattern p = Pattern.compile(strRegex); Matcher m = p.matcher(strInput); assertEquals(output,m.replaceAll(strReplacement)); }

Nota il \\ $ qui, che fa il trucco sfuggendo al carattere $ e facendo corrispondere con successo il modello.

6. Conclusione

In questo articolo, abbiamo esaminato i caratteri di escape nelle espressioni regolari in Java.

Abbiamo discusso del motivo per cui è necessario eseguire l'escape delle espressioni regolari e dei diversi modi in cui può essere ottenuto.

Come sempre, il codice sorgente relativo a questo articolo può essere trovato su GitHub.