JavaRush /Java Blog /Random-IT /Espressioni regolari in Java, parte 2

Espressioni regolari in Java, parte 2

Pubblicato nel gruppo Random-IT
Presentiamo alla vostra attenzione la traduzione di una breve guida alle espressioni regolari in Java, scritta da Jeff Friesen per il sito javaworld . Per facilitare la lettura abbiamo diviso l’articolo in più parti. Espressioni regolari in Java, parte 2 - 1Espressioni regolari in Java, parte 1
Unione di più intervalli
È possibile unire più intervalli in un'unica classe di caratteri di intervallo posizionandoli fianco a fianco. Ad esempio, la classe [a-zA-Z]corrisponde a tutti i caratteri alfabetici latini in minuscolo o maiuscolo.

Unione di più intervalli

È possibile unire più intervalli in un'unica classe di caratteri di intervallo posizionandoli fianco a fianco. Ad esempio, la classe [a-zA-Z]corrisponde a tutti i caratteri alfabetici latini in minuscolo o maiuscolo.

Combinazione di classi di personaggi

Un'unione di classi di caratteri è composta da diverse classi di caratteri nidificate e corrisponde a tutti i caratteri nell'unione risultante. Ad esempio, la classe [a-d[m-p]]corrisponde ai caratteri da aa de da ma p. Considera il seguente esempio: java RegexDemo [ab[c-e]] abcdef questo esempio troverà i caratteri a, b, c, de e, per i quali esistono corrispondenze in abcdef:
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4

Intersezione delle classi di caratteri

L'intersezione delle classi di caratteri è costituita da caratteri comuni a tutte le classi nidificate e corrisponde solo ai caratteri comuni. Ad esempio, la classe [a-z&&[d-f]]corrisponde ai caratteri d, ee f. Considera il seguente esempio: java RegexDemo "[aeiouy&&[y]]" party nota che sul mio sistema operativo Windows sono necessarie le virgolette doppie perché la shell dei comandi le tratta &come un separatore di comandi. In questo esempio verrà trovato solo il carattere yche ha una corrispondenza in party:
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4

Sottrazione delle classi di caratteri

La sottrazione delle classi di caratteri consiste in tutti i caratteri tranne quelli contenuti nelle classi di caratteri nidificate e corrisponde solo ai caratteri rimanenti. Ad esempio, la classe [a-z&&[^m-p]]corrisponde ai caratteri da aa le da qa z: java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg Questo esempio troverà i caratteri de fper i quali esistono corrispondenze in abcdefg:
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5

Classi di caratteri predefinite

Alcune classi di caratteri compaiono abbastanza frequentemente nelle espressioni regolari da giustificare l'uso della notazione abbreviata. La classe Patternoffre classi di caratteri predefinite come tali abbreviazioni. Puoi usarli per semplificare le tue espressioni regolari e ridurre al minimo gli errori di sintassi. Esistono diverse categorie di classi di caratteri predefinite: java.lang.Characterproprietà standard, POSIX e Unicode come script, blocco, categoria e binario. L'elenco seguente mostra solo la categoria delle classi standard:
  • \d: Numero. Equivalente [0-9].
  • \D: carattere non numerico. Equivalente [^0-9].
  • \s: carattere di spazio bianco. Equivalente [ \t\n\x0B\f\r].
  • \S: non è un carattere di spazio bianco. Equivalente [^\s].
  • \w: Simbolo di formazione delle parole. Equivalente [a-zA-Z_0-9].
  • \W: Non è un carattere che forma parole. Equivalente [^\w].
L'esempio seguente utilizza una classe di caratteri predefinita \wper descrivere tutti i caratteri verbali nel testo di input: java RegexDemo \w "aZ.8 _" Osserva attentamente i seguenti risultati di esecuzione, che mostrano che i caratteri punto e spazio non sono considerati caratteri verbali:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
Separatori di linea
La documentazione dell'SDK della classe Patterndescrive il metacarattere punto come una classe di caratteri predefinita che corrisponde a qualsiasi carattere tranne i separatori di riga (sequenze di uno o due caratteri che contrassegnano la fine di una riga). L'eccezione è la modalità dotall (di cui parleremo in seguito), in cui i punti corrispondono anche ai separatori di linea. La classe Patterndistingue i seguenti separatori di riga:
  • carattere di ritorno a capo ( \r);
  • carattere di nuova riga (simbolo per far avanzare la carta di una riga) ( \n);
  • un carattere di ritorno a capo immediatamente seguito da un carattere di nuova riga ( \r\n);
  • carattere della riga successiva ( \u0085);
  • carattere separatore di riga ( \u2028);
  • simbolo separatore di paragrafo ( \u2029)

Gruppi catturati

Il gruppo di acquisizione viene utilizzato per salvare la serie di caratteri trovata per un ulteriore utilizzo durante la ricerca per modello. Questo costrutto è una sequenza di caratteri racchiusi tra metacaratteri tra parentesi ( ( )). Tutti i caratteri all'interno del gruppo catturato vengono considerati come un unico insieme durante la ricerca per modello. Ad esempio, il gruppo di acquisizione ( Java) combina le lettere J, ae in una singola unità. Questo gruppo di acquisizione trova tutte le occorrenze del modello nel testo di input. Ad ogni corrispondenza i caratteri precedentemente memorizzati vengono sostituiti da quelli successivi. I gruppi acquisiti possono essere nidificati all'interno di altri gruppi acquisiti. Ad esempio, in un'espressione regolare, un gruppo è nidificato all'interno di un gruppo . A ogni gruppo di acquisizione nidificato o non nidificato viene assegnato un numero, a partire da 1, e la numerazione va da sinistra a destra. Nell'esempio precedente, corrisponde al gruppo di acquisizione numero 1 e corrisponde al gruppo di acquisizione numero 2. Nell'espressione regolare , corrisponde al gruppo di acquisizione numero 1 e al gruppo di acquisizione numero 2. È possibile accedere successivamente alle corrispondenze archiviate dai gruppi di acquisizione utilizzando i riferimenti all'indietro. Specificato come carattere barra rovesciata seguito da un carattere numerico corrispondente al numero del gruppo da acquisire, il riferimento all'indietro consente di fare riferimento ai caratteri nel testo acquisito dal gruppo. Avere un backlink fa sì che il matcher faccia riferimento al risultato di ricerca memorizzato del gruppo catturato in base al numero da esso, quindi utilizzi i caratteri di quel risultato per tentare un'ulteriore ricerca. L'esempio seguente mostra l'uso di un riferimento all'indietro per trovare errori grammaticali nel testo: Questo esempio utilizza un'espressione regolare per trovare un errore grammaticale con una parola duplicata immediatamente successiva nel testo di input . Questa espressione regolare specifica due gruppi da acquisire: numero 1 – , corrispondente a e numero 2 – , corrispondente al carattere spazio seguito da . Il backreference consente di rivisitare il risultato memorizzato del gruppo numero 2 in modo che il matcher possa cercare la seconda occorrenza di uno spazio seguito da , immediatamente dopo la prima occorrenza di uno spazio e . I risultati del matcher sono i seguenti: vaJavaJava(Java( language))(language)(Java)(Java( language))(language)(a)(b)(a)(b)Espressioni regolari in Java, parte 2 - 2java RegexDemo "(Java( language)\2)" "The Java language language"(Java( language)\2)languageJava"The Java language language"(Java( language)\2)Java language language(language)language\2languagelanguageRegexDemo
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25

Corrispondenze di confine

A volte è necessario eseguire una corrispondenza di pattern all'inizio di una riga, ai limiti delle parole, alla fine del testo, ecc. Puoi farlo utilizzando uno dei class edge matcher Pattern, che sono costrutti di espressioni regolari che cercano corrispondenze nelle seguenti posizioni:
  • ^: Inizio della riga;
  • $: Fine della riga;
  • \b: Confine di parola;
  • \B: confine della pseudoparola;
  • \A: Inizio del testo;
  • \G: Fine della partita precedente;
  • \Z: Fine del testo, escluso il separatore di riga finale (se presente);
  • \z: Fine del testo
L'esempio seguente utilizza il ^metacarattere Boundary Matcher per trovare righe che iniziano con The, seguite da zero o più caratteri alfanumerici: java RegexDemo "^The\w*" Therefore Il carattere ^specifica che i primi tre caratteri del testo di input devono corrispondere a caratteri di modello consecutivi T, he e, che possono essere seguiti da qualsiasi numero dei simboli che compongono le parole. Ecco il risultato dell'esecuzione:
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
Cosa succede se modifichi la riga di comando in java RegexDemo "^The\w*" " Therefore"? Non verrà trovata alcuna corrispondenza poiché Thereforeil testo immesso è preceduto da uno spazio.

Corrispondenze di lunghezza zero

A volte, quando si lavora con gli edge matcher, si riscontrano corrispondenze di lunghezza zero. Совпадение нулевой длиныè una corrispondenza che non contiene alcun carattere. Possono verificarsi nel testo di input vuoto, all'inizio del testo di input, dopo l'ultimo carattere del testo di input e tra due caratteri qualsiasi del testo di input. Le partite di lunghezza zero sono facili da riconoscere perché iniziano e finiscono sempre nella stessa posizione. Considera l'esempio seguente: java RegExDemo \b\b "Java is" questo esempio cerca due limiti di parole consecutive e i risultati sono simili a questi:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
Nei risultati vediamo diverse corrispondenze di lunghezza zero. Le posizioni finali qui sono una in meno rispetto alle posizioni iniziali, poiché RegexDemole ho specificate nel codice sorgente nel Listato 1 end() – 1. Espressioni regolari in Java, parte 2 - 3

Quantificatori

Un quantificatore è un costrutto di espressione regolare che associa esplicitamente o implicitamente un modello a un valore numerico. Questo valore numerico determina quante volte cercare il modello. I quantificatori si dividono in avidi, pigri e super-avidi:
  • Il quantificatore greedy ( ?, *o +) è progettato per trovare la corrispondenza più lunga. Posso chiedere X? per trovare una o meno occorrenze X, X*per trovare zero o più occorrenze X, X+per trovare una o più occorrenze X, X{n}per trovare noccorrenze X, X{n,}per trovare almeno (ed eventualmente più) noccorrenze Xe X{n,m}per trovare almeno nma non più moccorrenze X.
  • Il quantificatore pigro ( ??, *?o +?) è progettato per trovare la corrispondenza più breve. È possibile specificare X??di cercare una o meno occorrenze di X, X*? per trovare zero o più occorrenze X, X+?per trovare una o più occorrenze X, X{n}?per trovare noccorrenze X, X{n,}?per trovare almeno (e possibilmente più) noccorrenze Xe X{n,m}?per trovare almeno nma non più di moccorrenze X.
  • Il quantificatore super-avido ( ?+, *+o ++) è simile al quantificatore avido, tranne per il fatto che il quantificatore super-avido effettua solo un tentativo per trovare la corrispondenza più lunga, mentre il quantificatore avido può effettuare più tentativi. Può essere impostato X?+per trovare una o meno occorrenze X, X*+per trovare zero o più occorrenze X, X++per trovare una o più occorrenze X, X{n}+per trovare noccorrenze di X, X{n,}+per trovare almeno (ed eventualmente più) noccorrenze Xe X{n,m}+ per trovare almeno nma non più di moccorrenze X.
L'esempio seguente illustra l'uso del quantificatore greedy: java RegexDemo .*ox "fox box pox" Ecco i risultati:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
Il quantificatore goloso ( .*) trova la sequenza più lunga di caratteri che terminano con ox. Consuma l'intero testo di input e quindi esegue il rollback finché non rileva che il testo di input termina con questi caratteri. Consideriamo ora il quantificatore pigro: java RegexDemo .*?ox "fox box pox" I suoi risultati:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
Il quantificatore pigro ( .*?) trova la sequenza più breve di caratteri che terminano con ox. Inizia con una stringa vuota e consuma gradualmente i caratteri finché non trova una corrispondenza. E poi continua a lavorare fino all'esaurimento del testo di input. Infine, diamo un'occhiata al quantificatore super-avido: java RegexDemo .*+ox "fox box pox" ed ecco i suoi risultati:
regex = .*+ox
input = fox box pox
Il quantificatore extra-greedy ( .*+) non trova corrispondenze perché consuma tutto il testo di input e non c'è più nulla da abbinare oxalla fine dell'espressione regolare. A differenza del quantificatore avido, il quantificatore super-avido non torna indietro.

Corrispondenze di lunghezza zero

A volte, quando si lavora con i quantificatori, si incontrano corrispondenze di lunghezza zero. Ad esempio, utilizzando il seguente quantificatore greedy si ottengono più corrispondenze di lunghezza zero: java RegexDemo a? abaa I risultati dell'esecuzione di questo esempio:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
Ci sono cinque corrispondenze nei risultati dell'esecuzione. Sebbene il primo, il terzo e il quarto siano abbastanza attesi (corrispondono alle posizioni di tre lettere ain abaa), il secondo e il quinto potrebbero sorprendervi. Sembra che indichino ciò che acorrisponde balla fine del testo, ma in realtà non è così. L'espressione regolare a?non cerca balla fine del testo. Cerca presenza o assenza a. Quando a?non trova a, lo segnala come una corrispondenza di lunghezza zero.

Espressioni di flag nidificate

I matcher fanno alcuni presupposti predefiniti che possono essere sovrascritti durante la compilazione dell'espressione regolare in un modello. Discuteremo questo problema più tardi. Un'espressione regolare consente di sovrascrivere qualsiasi impostazione predefinita utilizzando un'espressione flag nidificata. Questo costrutto di espressione regolare è specificato come un metacarattere racchiuso tra parentesi attorno a un metacarattere punto interrogativo ( ?), seguito da una lettera latina minuscola. La classe Patterncomprende le seguenti espressioni flag nidificate:
  • (?i): attiva la corrispondenza dei modelli senza distinzione tra maiuscole e minuscole. Ad esempio, quando si utilizza un comando, java RegexDemo (?i)tree Treehousela sequenza di caratteri Treecorrisponde al modello tree. L'impostazione predefinita è la ricerca con pattern con distinzione tra maiuscole e minuscole.
  • (?x): consente l'uso di caratteri di spazio bianco e commenti che iniziano con il metacarattere all'interno del modello #. Il matcher li ignorerà entrambi. Ad esempio, per java RegexDemo ".at(?x)#match hat, cat, and so on" matteruna sequenza di caratteri matcorrisponde al modello .at. Per impostazione predefinita, gli spazi bianchi e i commenti non sono consentiti e il matcher li tratta come caratteri coinvolti nella ricerca.
  • (?s): abilita la modalità dotall, in cui il metacarattere punto corrisponde ai separatori di riga oltre a qualsiasi altro carattere. Ad esempio, il comando java RegexDemo (?s). \ntroverà un carattere di nuova riga. L'impostazione predefinita è l'opposto di dotall: non verrà trovato alcun separatore di riga. Ad esempio, il comando Java RegexDemo . \nnon troverà un carattere di nuova riga.
  • (?m): Abilita la modalità multilinea, dove ^corrisponde all'inizio e $alla fine di ogni riga. Ad esempio, java RegexDemo "(?m)^abc$" abc\nabctrova entrambe le sequenze nel testo di input abc. Per impostazione predefinita, viene utilizzata la modalità a riga singola: ^corrisponde all'inizio dell'intero testo di input e $alla fine. Ad esempio, java RegexDemo "^abc$" abc\nabcrestituisce una risposta che indica che non sono presenti corrispondenze.
  • (?u): abilita l'allineamento maiuscole/minuscole con distinzione tra Unicode. Questo flag, se utilizzato insieme a (?i), consente la corrispondenza di modelli senza distinzione tra maiuscole e minuscole in conformità con lo standard Unicode. L'impostazione predefinita prevede la ricerca solo di caratteri con distinzione tra maiuscole e minuscole e US-ASCII.
  • (?d): abilita la modalità stringa in stile Unix, in cui il matcher riconosce i metacaratteri nel contesto .e solo il separatore di riga . L'impostazione predefinita è la modalità stringa in stile non Unix: il matcher riconosce, nel contesto dei metacaratteri di cui sopra, tutti i delimitatori di riga.^$\n
Le espressioni flag nidificate assomigliano ai gruppi acquisiti perché i relativi caratteri sono racchiusi tra metacaratteri tra parentesi. A differenza dei gruppi acquisiti, le espressioni flag annidate sono un esempio di gruppi non acquisiti, che sono un costrutto di espressione regolare che non acquisisce caratteri di testo. Sono definiti come sequenze di caratteri circondate da metacaratteri di parentesi.
Specifica di più espressioni flag nidificate
È possibile specificare più espressioni flag nidificate in un'espressione regolare posizionandole una accanto all'altra ( (?m)(?i))) o posizionando le lettere che le definiscono in sequenza ( (?mi)).

Conclusione

Come probabilmente avrai ormai capito, le espressioni regolari sono estremamente utili e diventano ancora più utili man mano che padroneggi le sfumature della loro sintassi. Finora ti ho presentato le basi delle espressioni regolari e dei file Pattern. Nella Parte 2, esamineremo più in profondità l'API Regex ed esploreremo i metodi di Pattern, Matchere PatternSyntaxException. Ti mostrerò anche due applicazioni pratiche delle Regex API che potrai utilizzare subito nei tuoi programmi. Espressioni regolari in Java, Parte 3 Espressioni regolari in Java, Parte 4 Espressioni regolari in Java, Parte 5
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION