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 2

Pubblicato nel gruppo Random-IT
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. RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 2 - 1Quindi continuiamo!

Passaggio 8: stella *e segno più+

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 2 - 2Finora 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, GBo TB:
modello:
stringa:   11TB 13 14,4MB 22HB 9,9GB TB 0KB 
corrisponde: ^^^^ ^^^^^^ ^^^^^ ^^^  
( Soluzione )

Passaggio 9: punto interrogativo "facoltativo".?

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 2 - 3Hai 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 da l/ Le f/ Fper 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".|

RegEx: 20 brevi passaggi per padroneggiare le espressioni regolari.  Parte 2 - 4Nel 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:
  1. numeri con almeno una cifra a destra della virgola decimale
  2. numeri con almeno una cifra a sinistra della virgola decimale
Scriviamo le seguenti 2 espressioni regolari, indipendenti l'una dall'altra:
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, 6o .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
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION