JavaRush /Java Blog /Random-IT /RegEx: 20 brevi passaggi per padroneggiare le espressioni...
Artur
Livello 40
Tallinn

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 1

Pubblicato nel gruppo Random-IT
L'originale di questo articolo è qui . Probabilmente non esiste troppa teoria e alla fine dell'articolo fornirò diversi collegamenti a materiale più dettagliato sulle espressioni regolari. Ma mi è sembrato che iniziare ad approfondire un argomento come le espressioni regolari sarebbe stato molto più interessante se ci fosse stata l'opportunità non solo di stipare, ma anche di consolidare immediatamente le conoscenze completando piccoli compiti lungo il percorso. RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 1Iniziamo. Tipicamente gli oppositori all'uso delle espressioni regolari ("RegEx" o semplicemente "regex") nella programmazione citano la seguente citazione, attribuita a Jamie Zawinski: "Alcune persone, di fronte a un problema, pensano: 'Lo so, userò le espressioni regolari .""Ora hanno due problemi". In effetti, utilizzare le espressioni regolari non è ancora né una buona né una cattiva idea. E questo di per sé non aggiungerà problemi e non ne risolverà nessuno. È solo uno strumento. E il modo in cui lo usi (giusto o sbagliato) determina quali risultati vedrai. Se provi a utilizzare regex, ad esempio, per creare un parser HTML, molto probabilmente riscontrerai problemi . Ma se vuoi solo estrarre, ad esempio, i timestamp da alcune righe, probabilmente andrà tutto bene. Per semplificarti la padronanza delle espressioni regolari, ho messo insieme questa lezione che ti aiuterà a padroneggiarle da zero in soli venti brevi passaggi. Questo tutorial si concentra principalmente sui concetti di base delle espressioni regolari e approfondisce argomenti più avanzati solo se necessario.

Passaggio 1: perché utilizzare le espressioni regolari

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 2Le espressioni regolari vengono utilizzate per cercare corrispondenze nel testo utilizzando modelli specificati (modelli). Utilizzando regex, possiamo estrarre facilmente e semplicemente parole dal testo, nonché singoli caratteri letterali e metacaratteri e le loro sequenze che soddisfano determinati criteri. Ecco cosa ci dice Wikipedia al riguardo : Le espressioni regolari sono un linguaggio formale per la ricerca e la manipolazione di sottostringhe nel testo, basato sull'uso di metacaratteri (caratteri jolly). Per la ricerca viene utilizzata una stringa di esempio (modello inglese, in russo è spesso chiamato "modello", "maschera"), composta da simboli e metasimboli e che definisce la regola di ricerca. Per manipolare il testo viene inoltre specificata una stringa sostitutiva che può contenere anche caratteri speciali. Lo schema può essere semplice come la parola dogin questa frase:
La veloce volpe marrone salta sopra il cane pigro.
Questa espressione regolare assomiglia a questa:
cane
... Abbastanza facile, non è vero? Il modello può anche essere qualsiasi parola che contenga la lettera o. Un'espressione regolare per trovare un modello di questo tipo potrebbe assomigliare a questa:
\ Oh * _
( Puoi provare questa espressione regolare qui .) Noterai che man mano che i requisiti di "corrispondenza" diventano più complessi, anche l'espressione regolare diventa più complessa. Esistono ulteriori forme di notazione per specificare gruppi di caratteri e abbinare modelli ripetuti, che spiegherò di seguito. Ma non appena troviamo una corrispondenza con uno schema in qualche testo, cosa possiamo farne? I moderni motori di espressioni regolari consentono di estrarre caratteri o sequenze di caratteri (sottostringhe) dal testo contenuto, oppure rimuoverli o sostituirli con altro testo. In generale, le espressioni regolari vengono utilizzate per analizzare e manipolare il testo. Possiamo estrarre, ad esempio, sottostringhe che assomigliano a indirizzi IP e poi provare a verificarle. Oppure possiamo estrarre nomi e indirizzi email e archiviarli in un database. Oppure utilizza le espressioni regolari per trovare informazioni sensibili (come numeri di passaporto o numeri di telefono) nelle e-mail e avvisare l'utente che potrebbe mettersi a rischio. Regex è davvero uno strumento versatile, facile da imparare ma difficile da padroneggiare: “Proprio come c’è differenza tra suonare bene un brano musicale e creare musica, c’è differenza tra conoscere le espressioni regolari e capirle”. - Jeffrey E. F. Friedl, Padroneggiare le espressioni regolari

Passaggio 2: parentesi quadre[]

Le espressioni regolari più semplici e facili da comprendere sono quelle che cercano semplicemente una corrispondenza carattere per carattere tra il modello dell'espressione regolare e la stringa di destinazione. Proviamo, ad esempio, a trovare un gatto: RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 3
modello: gatto
stringa: Il gatto è stato tagliato mentre correva sotto la macchina.
corrispondenze:      ^^^
( Come funziona in pratica - vedi qui ) ATTENZIONE! Tutte le soluzioni sono presentate qui solo come possibili soluzioni. Nelle espressioni regolari, come nella programmazione in generale, è possibile risolvere gli stessi problemi in modi diversi. Tuttavia, oltre a un rigoroso confronto carattere per carattere, possiamo anche specificare corrispondenze alternative utilizzando parentesi quadre:
modello: ca[rt]
stringa: Il gatto è stato tagliato mentre correva sotto la macchina.
corrispondenze:      ^^^ ^^^
( Come funziona ) Le parentesi quadre aperte e chiuse indicano al motore delle espressioni regolari che deve corrispondere a uno qualsiasi dei caratteri specificati, ma solo a uno. L'espressione regolare di cui sopra non troverà, ad esempio, l' cartintera parola, ma ne troverà solo una parte:
modello: ca[rt]
stringa: Il gatto è stato tagliato mentre correva sotto il carro.
corrispondenze:      ^^^ ^^^
( Come funziona ) Quando usi le parentesi quadre, dici al motore delle espressioni regolari di abbinare solo uno dei caratteri contenuti tra parentesi. Il motore trova il carattere c, poi il carattere a, ma se il carattere successivo non è ro t, la corrispondenza non è completa. Se trova ca, e poi r, o t, si ferma. Non tenterà di abbinare più caratteri perché le parentesi quadre indicano che è necessario abbinare solo uno dei caratteri contenuti. Quando trova ca, trova rla parola next carte si ferma perché ha già trovato una corrispondenza per la sequenza car.

Obiettivi formativi:

Scrivi un'espressione regolare che corrisponda a tutti e 10 i modelli hadin Hadquesto estratto di giochi di parole intraducibili nel dialetto locale:
modello:
stringa: Jim, dove Bill aveva "avuto" , aveva avuto "aveva avuto" . "Aveva avuto" era corretto.
corrispondenze:                  ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^ ^^^
( Vedi la possibile soluzione qui ) Che dire di tutti i nomi di animali nella frase seguente?
modello:
stringa: Un pipistrello, un gatto e un topo sono entrati in un bar...
corrispondenze:    ^^^ ^^^ ^^^
( Possibile soluzione ) O ancora più semplice: trova le parole baroppure bat:
modello:
stringa: Un pipistrello, un gatto e un topo sono entrati in un bar...
corrispondenze:    ^^^ ^^^
( Possibile soluzione ) Adesso abbiamo già imparato a scrivere espressioni regolari più o meno complesse, e siamo solo al passo 2! Continuiamo!

Passaggio 3: sequenze di fuga

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 4Nel passaggio precedente abbiamo imparato a conoscere le parentesi quadre []e come ci aiutano a trovare corrispondenze alternative utilizzando il motore regex. Ma cosa succede se vogliamo trovare corrispondenze sotto forma di parentesi quadre aperte e chiuse stesse []? Quando volevamo trovare una corrispondenza carattere per carattere della parola cat, abbiamo fornito al motore regex questa sequenza di caratteri ( cat). Proviamo a trovare le parentesi quadre []allo stesso modo:
pattern: [] 
string: Non puoi far corrispondere [] usando regex! Te ne pentirai!
partite: 
( Vediamo cosa è successo ) Qualcosa non ha funzionato, tuttavia... Questo perché i caratteri tra parentesi quadre agiscono come caratteri speciali del motore regex che vengono solitamente utilizzati per indicare qualcos'altro e non sono uno schema letterale per abbinarli a loro stessi. Come ricordiamo dal passaggio 2, vengono utilizzati per trovare corrispondenze alternative in modo che il motore regex possa abbinare qualsiasi carattere contenuto tra di loro. Se non inserisci alcun carattere tra di loro, potrebbe causare un errore. Per far corrispondere questi caratteri speciali, dobbiamo eseguirne l'escape facendoli precedere da un carattere barra rovesciata \. La barra rovesciata (o barra rovesciata) è un altro carattere speciale che dice al motore regex di cercare letteralmente il carattere successivo, invece di usarlo come metacarattere. Il motore regex cercherà i caratteri solo [e ]letteralmente se sono entrambi preceduti da una barra rovesciata:
modello: \[\]
stringa: non è possibile abbinare [] utilizzando l'espressione regolare! Te ne pentirai!
corrispondenze:                  ^^ 
( Vediamo cosa è successo questa volta ) OK, e se volessimo trovare la barra rovesciata stessa? La risposta è semplice. Poiché \anche la barra rovesciata è un carattere speciale, è necessario eseguire anche l'escape. Come? Barra rovesciata!
modello: \\
stringa: C:\Utenti\Tanja\Immagini\Cani
corrispondenze:    ^ ^ ^ ^
( Stesso esempio in pratica ) Solo i caratteri speciali devono essere preceduti da una barra rovesciata. Tutti gli altri caratteri vengono interpretati letteralmente per impostazione predefinita. Ad esempio, l'espressione regolare tcorrisponde letteralmente solo talle lettere minuscole:
modello: t
stringa: tttt
corrispondenze: ^ ^ ^ ^
( Esempio ) Tuttavia, questa sequenza \tfunziona in modo diverso. È un modello per la ricerca di un carattere di tabulazione:
modello: \t
stringa: tttt
corrispondenze:   ^ ^ ^
( Esempio ) Alcune sequenze di escape comuni includono \n(interruzioni di riga in stile UNIX) e \r(utilizzate nelle interruzioni di riga in stile Windows \r\n). \rè un carattere di "ritorno a capo" ed \nè un carattere di "avanzamento riga", entrambi definiti insieme allo standard ASCII quando le telescriventi erano ancora ampiamente utilizzate. Altre sequenze di escape comuni verranno trattate più avanti in questo tutorial.

Nel frattempo, rinforziamo il materiale con un paio di semplici enigmi:

Prova a scrivere un'espressione regolare per trovare... un'espressione regolare ;) Il risultato dovrebbe essere qualcosa del genere:
modello:
string: ...abbina questa regex ` \[\] ` con una regex?
corrispondenze:                       ^^^^	
( Soluzione ) Ci sei riuscito? Ben fatto! Ora prova a creare una regex per cercare sequenze di escape come questa:
modello:
stringa: ` \r `, ` \t ` e ` \n ` sono tutte sequenze di escape regex.
corrispondenze:   ^^ ^^ ^^
( Soluzione )

Passaggio 4: cerca "qualsiasi" carattere utilizzando un punto.

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 5Durante la scrittura delle soluzioni di corrispondenza della sequenza di escape che abbiamo visto nel passaggio precedente, potresti esserti chiesto: "Posso abbinare il carattere barra rovesciata e poi qualsiasi altro carattere che lo segue?"... Certo che puoi! C'è un altro carattere speciale che viene utilizzato per corrispondere a (quasi) qualsiasi carattere: il carattere punto (punto). Ecco cosa fa:
modello: .
stringa: Mi dispiace, Dave. Temo di non poterlo fare.
corrispondenze: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^	
( Esempio ) Se vuoi abbinare solo modelli che assomigliano a sequenze di escape, puoi fare qualcosa del genere:
modello: \\. 
string: Ciao Walmart, mio ​​nipote si chiama " \n \r \t ".
corrispondenze:                                              ^^ ^^ ^^	
( Esempio ) E, come con tutti i caratteri speciali, se vuoi far corrispondere un valore letterale ., devi farlo precedere da un carattere \:
modello: \. 
stringa: La guerra è pace . La libertà è schiavitù . L'ignoranza è forte . 
corrispondenze:             ^ ^ ^
( Esempio )

Passaggio 5: intervalli di caratteri

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 6Cosa succede se non hai bisogno di simboli, ma vuoi trovare solo lettere nel testo? O numeri? O vocali? La ricerca per classi di personaggi e i loro intervalli ci consentirà di raggiungere questo obiettivo.
` \n `, ` \r ` e ` \t ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .	
I caratteri sono "spazi bianchi" se non creano un segno visibile nel testo. Uno spazio " " è uno spazio, un'interruzione di riga o una tabulazione. Diciamo che vogliamo trovare sequenze di escape che rappresentino solo caratteri di spazio bianco \n, \re \tnel passaggio precedente, ma non altre sequenze di escape. Come potremmo farlo?
modello: \\[nrt] 
stringa: ` \n `, ` \r ` e ` \t ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:   ^^ ^^ ^^	
( Esempio ) Funziona, ma non è una soluzione molto elegante. Cosa succede se in seguito dobbiamo abbinare la sequenza di escape per il carattere "form feed", \f? (Questo simbolo viene utilizzato per indicare interruzioni di pagina nel testo.)
modello: \\[nrt] 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:   ^^ ^^ ^^	
( Soluzione non funzionante ) Con questo approccio, dobbiamo elencare separatamente ciascuna lettera minuscola che vogliamo far corrispondere, tra parentesi quadre. Un modo più semplice per farlo è utilizzare intervalli di caratteri per corrispondere a qualsiasi lettera minuscola:
modello: \\[az] 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:   ^^ ^^ ^^ ^^	
( E questo funziona già ) Gli intervalli di caratteri funzionano come ci si potrebbe aspettare, dato l'esempio sopra. Inserisci parentesi quadre attorno alla prima e all'ultima lettera che desideri abbinare, con un trattino in mezzo. Ad esempio, se desideri trovare solo "set" di barre rovesciate \e una lettera da aa m, potresti procedere come segue:
modello: \\[am] 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:                         ^^	
( Esempio ) Se desideri abbinare più intervalli, posizionali semplicemente uno dopo l'altro tra parentesi quadre:
modello: \\[a-gq-z] 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:         ^^ ^^ ^^	
( Esempio ) Altri intervalli di caratteri comuni includono: A-Ze0-9

Proviamoli in pratica e risolviamo un paio di problemi:

I numeri esadecimali possono contenere sia cifre 0-9che lettere A-F. Se utilizzati per specificare i colori, i codici esadecimali possono contenere un massimo di tre caratteri. Crea un'espressione regolare per trovare codici esadecimali validi nell'elenco seguente:
modello:
corda: 1H8 4E2 8FF 0P1 T8B 776 42B G12
corrispondenze:      ^^^ ^^^ ^^^ ^^^	
( Soluzione ) Utilizzando gli intervalli di caratteri, crea un'espressione regolare che selezionerà solo le consonanti minuscole (non le vocali, incluso y) nella frase seguente:
modello:stringa 
: I muri del centro commerciale sono totalmente , totalmente alti . _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
corrispondenze:   ^ ^ ^^^ ^ ^^ ^ ^^ ^ ^ ^ ^^^ ^ ^ ^^^ ^ ^^	
( Soluzione )

Passo 6: "non", accento circonflesso, accento circonflesso... simbolo^

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 1 - 7In verità, ci sono più di 9000 nomi per questo simbolo :) Ma, per semplicità, forse ci concentreremo sul “non”. La mia soluzione all'ultimo problema è un po' lunga. Ci sono voluti 17 caratteri per dire "prendi l'intero alfabeto tranne le vocali". Naturalmente esiste un modo più semplice per farlo. Il segno "not" ^ci consente di specificare caratteri e intervalli di caratteri che non devono corrispondere a quelli specificati nel modello. Una soluzione più semplice all'ultimo problema di cui sopra è trovare caratteri che non rappresentano vocali:
modello : [ ^ aeiou ] stringa 
:   I muri del centro commerciale sono davvero alti . _ _ _ _ _ _ _ _ _ _ _ _ 
corrispondenze: ^^ ^^ ^^^^ ^^^^ ^^ ^^^ ^ ^^ ^ ^^^^^^ ^ ^^^^^ ^^^ 	
( Esempio ) Il segno "not" ^come carattere più a sinistra tra parentesi quadre []indica al motore delle espressioni regolari di corrispondere a un (qualsiasi) carattere che non si trova tra parentesi quadre. Ciò significa che l'espressione regolare di cui sopra corrisponde anche a tutti gli spazi, i punti ., le virgole ,e le maiuscole Tall'inizio di una frase. Per escluderli possiamo anche metterli tra parentesi quadre:
modello : [ ^ aeiou . , T ] stringa  
: I muri del centro commerciale sono davvero alti . _ _ _ _ _ _ _ _ _ _ _ _ 
corrispondenze:   ^ ^ ^^^ ^ ^^ ^ ^^ ^ ^ ^ ^^^ ^ ^ ^^^ ^ ^^	
( Esempio ) Notache in questo caso non abbiamo bisogno di evitare il punto con una barra rovesciata, come abbiamo fatto prima quando lo cercavamo senza usare le parentesi quadre. Molti caratteri speciali tra parentesi quadre vengono trattati letteralmente, compreso il carattere della parentesi aperta [, ma non quello di chiusura ](puoi indovinare perché?). Anche il carattere barra rovesciata \non viene interpretato letteralmente. Se desideri far corrispondere una barra rovesciata letterale \utilizzando parentesi quadre, devi eseguire l'escape facendola precedere dalla barra rovesciata seguente \\. Questo comportamento è stato progettato in modo che i caratteri degli spazi bianchi possano essere inseriti anche tra parentesi quadre per la corrispondenza:
modello: [\t]
stringa: tttt
corrispondenze:   ^ ^ ^
( Esempio ) Il segno "not" ^può essere utilizzato anche con gli intervalli. Se volessi catturare solo i caratteri a, b, c, x, ye z, potrei fare qualcosa del genere:
modello: [abcxyz] 
stringa:   abc defghijklmnopqrstuvw xyz 
corrisponde a: ^^^ ^^^
( Esempio ) ...oppure, potrei specificare che voglio trovare qualsiasi carattere che non sia compreso tra de w:
modello: [^dw] 
stringa:   abc defghijklmnopqrstuvw xyz 
corrisponde a: ^^^ ^^^
( Esempio ) Tuttavia,stai attentocon "non" ^. È facile pensare "beh, ho specificato [^ b-f], quindi dovrei ottenere una lettera minuscola ao qualcosa del genere dopo f. Non è così. Questa regex corrisponderà a qualsiasi carattere non compreso in quell'intervallo, comprese lettere, numeri, punteggiatura e spazi.
modello: [^dw] 
stringa:   abc defg h . i , j - klmnopqrstuvw xyz 
corrisponde a: ^^^ ^ ^ ^ ^ ^^^
( Esempio )

Attività di aumento di livello:

Utilizza il segno "non" ^tra parentesi quadre per abbinare tutte le parole seguenti che non terminano con y:
modello:
stringa: day dog ​​hog hay bog bay ray rub 
corrispondenze:      ^^^ ^^^ ^^^ ^^^	
( Soluzione ) Scrivi un'espressione regolare utilizzando un intervallo e un segno "non" ^per trovare tutti gli anni tra il 1977 e il 1982 (incluso):
modello:
stringa: 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984
corrispondenze:            ^^^^ ^^^^ ^^^^ ^^^^ ^^^^ ^^^^
( Soluzione ) Scrivi un'espressione regolare per trovare tutti i caratteri che non sono un segno "not" ^:
modello:
stringa:   abc1 ^ 23*() 
corrisponde a: ^^^^ ^^^^^	
( Soluzione )

Passaggio 7: classi di personaggi

Le classi di caratteri sono ancora più semplici degli intervalli di caratteri. Diversi motori di espressioni regolari hanno classi diverse disponibili, quindi qui tratterò solo quelle principali. (Controlla quale versione di regex stai utilizzando, perché potrebbero essercene di più o potrebbero essere diverse da quelle mostrate qui.) Le classi di caratteri funzionano quasi come intervalli, ma non puoi specificare i valori "inizio" e "fine":
Classe simboli
\d "numeri"[0-9]
\w "simboli verbali"[A-Za-z0-9_]
\s "spazi"[ \t\r\n\f]
La classe di caratteri "parola" \wè particolarmente utile perché questo set di caratteri è spesso richiesto per identificatori validi (nomi di variabili, nomi di funzioni, ecc.) in vari linguaggi di programmazione. Possiamo usare \wper semplificare l'espressione regolare che abbiamo visto prima:
modello: \\[az] 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:   ^^ ^^ ^^ ^^	
Usando \wpossiamo scrivere così:
modello: \\\w 
stringa: ` \n `, ` \r `, ` \t ` e ` \f ` sono caratteri di spazio bianco, ` \. `, ` \\ ` e ` \[ ` non lo sono .
corrispondenze:   ^^ ^^ ^^ ^^	
( Esempio )

2 compiti per fortuna:

Come tu e io sappiamo, in Java, un identificatore (nome di una variabile, classe, funzione, ecc.) può iniziare solo con la lettera a- zA- Z, il simbolo del dollaro $o il carattere di sottolineatura _. ( sottolineare è, ovviamente, uno stile pessimo, ma il compilatore lo salta, nota del traduttore ). Il resto dei caratteri deve essere caratteri "parola" \w. Utilizzando una o più classi di caratteri, crea un'espressione regolare per cercare identificatori Java validi tra le seguenti sequenze di tre caratteri:
modello:
stringa:   __e $12 .x2 foo Barra 3mm
corrispondenze: ^^^ ^^^ ^^^ ^^^	
( Soluzione ) I numeri di previdenza sociale (SSN) statunitensi sono numeri di 9 cifre nel formato XXX-XX-XXXX, dove ogni X può essere qualsiasi cifra [0-9]. Utilizzando una o più classi di caratteri, scrivi un'espressione regolare per trovare i SSN formattati correttamente nell'elenco seguente:
modello:
stringa: 113-25=1902 182-82-0192 H23-_3-9982 1I1-O0-E38B
corrispondenze:              ^^^^^^^^^^^
( Soluzione ) RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 2. 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 3. RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 4.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION