RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 1 Originale qui Nell'ultima parte abbiamo imparato le espressioni regolari più semplici e abbiamo già imparato qualcosa. In questa parte studieremo progetti un po' più complessi, ma credetemi, non sarà così difficile come potrebbe sembrare. Quindi continuiamo!
Passaggio 8: stella
Finora siamo riusciti più o meno a far corrispondere solo stringhe di una determinata lunghezza. Ma negli ultimi problemi ci siamo avvicinati al limite di ciò che possiamo fare con la notazione vista finora. Supponiamo, ad esempio, di non essere limitati a identificatori Java di 3 caratteri, ma di poter avere identificatori di qualsiasi lunghezza. Una soluzione che potrebbe aver funzionato nell'esempio precedente non funzionerà nell'esempio seguente:
Passaggio 9: punto interrogativo "facoltativo".
Hai già scritto regex per risolvere l'ultimo problema? Ha funzionato? Ora prova ad applicarlo qui:
Passaggio 10: segno "o".
Nel passaggio 8 abbiamo avuto qualche difficoltà nel trovare i diversi tipi di numeri in virgola mobile:
Passaggio 8: stella *
e segno più+
Finora siamo riusciti più o meno a far corrispondere solo stringhe di una determinata lunghezza. Ma negli ultimi problemi ci siamo avvicinati al limite di ciò che possiamo fare con la notazione vista finora. Supponiamo, ad esempio, di non essere limitati a identificatori Java di 3 caratteri, ma di poter avere identificatori di qualsiasi lunghezza. Una soluzione che potrebbe aver funzionato nell'esempio precedente non funzionerà nell'esempio seguente:
modello: [a-zA-Z_$]\w\w stringa: __e $12 3 3.2 fo Barra r a23 mm ab x corrispondenze: ^^^ ^^^ ^^^ ^^^( Esempio ) Notache quando un identificatore è valido ma più lungo di 3 caratteri, vengono abbinati solo i primi tre caratteri. E quando l'identificatore è valido, ma contiene meno di 3 caratteri, la regex non lo trova affatto! Il problema è che le espressioni tra parentesi
[]
corrispondono esattamente a un carattere, così come le classi di caratteri come \w
. Ciò significa che qualsiasi corrispondenza nell'espressione regolare sopra deve essere lunga esattamente tre caratteri. Quindi non funziona così bene come avremmo potuto sperare. *
I caratteri speciali e possono aiutare qui +
. Si tratta di modificatori che possono essere aggiunti a destra di qualsiasi espressione per corrispondere a quell'espressione più di una volta. La stella Kleene (o "asterisco") *
indicherà che il token precedente deve essere abbinato un numero qualsiasi di volte, comprese zero volte. Il segno più +
indicherà che è necessario effettuare la ricerca una o più volte. Pertanto, l'espressione che precede +
è obbligatoria (almeno una volta), mentre l'espressione che precede *
è facoltativa, ma quando appare può apparire un numero qualsiasi di volte. Ora, con questa conoscenza, possiamo correggere l'espressione regolare di cui sopra:
modello: [a-zA-Z_$]\w* stringa: __e $123 3.2 fo Barr a23mm ab x corrisponde a: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ ^( Esempio ) Ora abbiniamo identificatori validi di qualsiasi lunghezza! Bingo! Ma cosa accadrebbe se utilizzassimo ?
+
invece di *
?
modello: [a-zA-Z_$]\w+ stringa: __e $123 3.2 fo Barr a23mm ab x corrispondenze: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^( Esempio ) Abbiamo perso l'ultima partita,
х
. Questo perché richiede +
la corrispondenza di almeno un carattere, ma poiché l'espressione tra parentesi []
che precede \w+
ha già "mangiato" il carattere x
, non ci sono più caratteri disponibili, quindi la corrispondenza fallisce. Quando possiamo usarlo +
? Quando dobbiamo trovare almeno una corrispondenza, ma non importa quante volte deve corrispondere una determinata espressione. Ad esempio, se vogliamo trovare numeri contenenti un punto decimale:
modello: \d*\.\d+ stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 corrispondenze: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^( Esempio ) Notache rendendo facoltativi i numeri a sinistra del punto decimale, siamo riusciti a trovare sia 0,011 che 0,2. Per fare ciò, dovevamo far corrispondere esattamente una virgola decimale con
\.
e almeno una cifra a destra della virgola decimale con \d+
. L'espressione regolare di cui sopra non corrisponderà a un numero come 3.
, perché abbiamo bisogno di almeno una cifra a destra del separatore decimale per corrispondere.
Come al solito, risolviamo un paio di semplici problemi:
Trova tutte le parole inglesi nel passaggio sottostante.modello: stringa: 3 più 3 fa sei ma 4 più tre fa 7 corrispondenze: ^^^^ ^^ ^^^ ^^^ ^^^^ ^^^^^ ^^( Soluzione ) Trova tutti i simboli delle dimensioni dei file nell'elenco seguente. Le dimensioni dei file saranno composte da un numero (con o senza punto decimale) seguito da
KB
, MB
, GB
o TB
:
modello: stringa: 11TB 13 14,4MB 22HB 9,9GB TB 0KB corrisponde: ^^^^ ^^^^^^ ^^^^^ ^^^( Soluzione )
Passaggio 9: punto interrogativo "facoltativo".?
Hai già scritto regex per risolvere l'ultimo problema? Ha funzionato? Ora prova ad applicarlo qui:
modello: stringa: 1..3KB 5...GB ..6TB partite:Ovviamente, nessuna di queste designazioni è una dimensione di file valida, quindi una buona espressione regolare non dovrebbe corrispondere a nessuna delle due. La soluzione che ho scritto per risolvere l'ultimo problema li corrisponde a tutti, almeno in parte:
modello: \d+\.*\d*[KMGT]B stringa: 1..3KB 5...GB .. 6TB corrispondenze: ^^^^^^ ^^^^^^ ^^^( Esempio ) Allora qual è il problema? In effetti, dobbiamo trovare solo un punto decimale, se ce n'è uno. Ma
*
consente qualsiasi numero di corrispondenze, incluso zero. C'è un modo per abbinare solo zero volte o una volta? Ma non più di una volta? Naturalmente sì. "opzionale" ?
è un modificatore che corrisponde a zero o uno dei caratteri precedenti, ma non di più:
modello: \d+\.?\d*[KMGT]B stringa: 1.. 3KB 5...GB .. 6TB corrispondenze: ^^^ ^^^( Esempio ) Siamo più vicini a una soluzione, ma non è proprio ciò di cui abbiamo bisogno. Vedremo come risolvere questo problema in pochi passaggi un po' più tardi.
Intanto risolviamo questo problema:
In alcuni linguaggi di programmazione (ad esempio Java), alcuni numeri interi e in virgola mobile (punto) possono essere seguiti dal
/ L
e f
/ F
per indicare che devono essere trattati come long/float (rispettivamente) anziché come normali int/double. Trova tutti i numeri "lunghi" validi nella riga seguente:
modello: stringa: 13L lungo 2l 19 L lL 0 corrisponde: ^^^ ^^ ^^ ^( Soluzione )
Passaggio 10: segno "o".|
Nel passaggio 8 abbiamo avuto qualche difficoltà nel trovare i diversi tipi di numeri in virgola mobile:
modello: \d*\.\d+ stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 corrispondenze: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^Il modello precedente corrisponde ai numeri con una virgola decimale e almeno una cifra a destra della virgola decimale. Ma cosa succede se vogliamo abbinare anche stringhe come
0.
? (Nessun numero a destra del punto decimale.) Potremmo scrivere un'espressione regolare come questa:
modello: \d*\.\d* stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . corrispondenze: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ ^( Esempio ) Questo corrisponde a
0.
, ma corrisponde anche a un singolo punto .
, come puoi vedere sopra. In realtà ciò che stiamo cercando di abbinare sono due diverse classi di stringhe:
- numeri con almeno una cifra a destra della virgola decimale
- numeri con almeno una cifra a sinistra della virgola decimale
modello: \d*\.\d+ stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . corrispondenze: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^
modello: \d+\.\d* stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . corrispondenze: ^^^^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^Vediamo che in nessuno di questi casi le sottostringhe
42
, 5
, 6
o .
vengono trovate dal motore. Per ottenere il risultato richiesto, non sarebbe male combinare queste espressioni regolari. Come possiamo raggiungere questo risultato? Il segno "o" |
ci consente di specificare diverse possibili sequenze di corrispondenze contemporaneamente in un'espressione regolare. Proprio come []
il segno "o" ci consente di specificare caratteri singoli alternativi, |
possiamo specificare espressioni alternative composte da più caratteri. Ad esempio, se volessimo trovare "cane" o "gatto", potremmo scrivere qualcosa del genere:
pattern: \w\w\w string: Ovviamente , un cane è un animale domestico migliore di un gatto . corrispondenze: ^^^^^^^^^ ^^^ ^^^^^^ ^^^ ^^^ ^^^( Esempio ) ... ma corrisponde a tutte le sequenze di tre caratteri della classe "parola". Ma "cane" e "gatto" non hanno nemmeno lettere in comune, quindi le parentesi quadre non ci aiutano qui. Ecco l'espressione regolare più semplice che potremmo usare che corrisponde a entrambe e solo a queste due parole:
pattern: cane|gatto stringa: Ovviamente, un cane è un animale domestico migliore di un gatto . corrispondenze: ^^^ ^^^( Esempio ) Il motore delle espressioni regolari tenta innanzitutto di far corrispondere l'intera sequenza a sinistra del carattere
|
, ma se fallisce, tenta quindi di far corrispondere la sequenza a destra del carattere |
. |
È inoltre possibile concatenare più caratteri per corrispondere a più di due sequenze alternative:
pattern: dog|cat|pet stringa: Ovviamente, un cane è un animale domestico migliore di un gatto . corrispondenze: ^^^ ^^^ ^^^( Esempio )
Ora risolviamo un altro paio di problemi per comprendere meglio questo passaggio:
Utilizza il segno|
per correggere l'espressione regolare decimale sopra per produrre un risultato come questo:
modello: stringa: 0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . corrispondenze: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^( Soluzione ) Utilizzare sign
|
, classi di caratteri, "optional" ?
, ecc. per creare una singola espressione regolare che corrisponda sia ai numeri interi che a quelli in virgola mobile (punto), come discusso nel problema alla fine del passaggio precedente (questo problema un po' più complicato, sì ;))
modello: stringa: 42L 12 x 3.4f 6l 3.3 0F LF .2F 0. corrisponde a: ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^( Soluzione ) 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 3 RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari. Parte 4
GO TO FULL VERSION