Informatica di base

Caratteri e bordi nelle espressioni regolari

Autore

Manuel Ricci

Quello che abbiamo visto finora è stato abbastanza semplice e, spero, comprensibile. Le espressioni regolari sanno essere strumenti molto potenti, ma possiamo anche utilizzarle anche per cose semplicissime come cercare un carattere o una parola, infischiandocene magari di maiuscole o minuscole o se questa sia effettivamente la parola esatta o se fa parte di una parola più lunga. Un po’ come quando facciamo una ricerca all’interno di una pagina web, cerchiamo una parola e scorriamo le varie corrispondenze alla ricerca della parte che stiamo cercando.

La peculiarità delle regexp è che possono essere affinate per poter restringere il numero di risultati ad esattamente ciò che stiamo cercando e il potenziale è pressoché illimitato.

Caratteri e bordi

Abbiamo già incontrato nelle lezioni precedenti il terminatore \b e sappiamo, grazie alla lezione precedente, che esiste anche \B e che il suo significato è tutto ciò che non è \b, che possiamo parafrasare in: il contrario di \b.

Mentre quindi \b individua il bordo di una parola (e poi chiariremo meglio questo aspetto), \w è l’identificatore del carattere e sempre dalla lezione precedente sappiamo anche che esiste il suo gemello contrario \W. Ormai avrete capito che quando un’entità ha una controparte maiuscola, quest’ultima è sempre contraria.

Ma andiamo con ordine…

Bordi di parole con \b

Supponiamo di avere questa frase:

Non mi piace la sabbia. È granulosa, ruvida, e irrita la pelle, e s’infila dappertutto.

Vogliamo individuare tutte le parole con 6 lettere, come facciamo? Usiamo un po’ la fantasia e attingiamo con logica dalle entità viste nella lezione precedente. Potremmo scrivere:

1\s……\s

Potrebbe essere una soluzione se le parole fossero singole, ma, in questo caso, sabbia, ruvida e infila vengono escluse.

Il . (punto) è un carattere jolly che cerca qualsiasi carattere (escluso \n).

Proviamo quindi con:

1\b……\b

Direi un po’ too much. Abbiamo selezionato le parole, ma le corrispondenze si estendono anche a parole che non c’entrano niente e che hanno spazi tra le lettere. Questo sempre per colpa dell’impiego del punto.

\b e la dimensione zero

So che sembra un termine fantascientifico, ma la dimensione zero possiamo tradurla in ancoraggio.

\b, come \B è un ancoraggio e per ancoraggio si intende quelle istruzioni che ci ancorano la regular expression in una posizione specifica all’interno della stringa di testo.

Possiamo quindi affermare che un ancoraggio non individua i caratteri, ma bensì il punto di separazione.

Altri ancoraggi sono, ad esempio $ e ^ che rispettivamente posizionano la regex alla fine e all’inizio della stringa.

Provando ad inserire \b in regex101.com vediamo che le linee tratteggiate viola si collocano esattamente tra la lettera e il carattere non lettera (spazio, punteggiature, ecc.)

esempio bordo espressione regolare

Tornando alla nostra frase proviamo quindi un ulteriori soluzione:

1\b[a-zAZ][a-zAZ][a-zAZ][a-zAZ][a-zAZ][a-zAZ]\b

A questo giro funziona, ma è a prova di tutto? Purtroppo no, modifichiamo leggermente la frase come segue:

Non mi piace la sabbia. Perché granulosa, ruvida, e irrita la pelle, e s’infila dappertutto.

Perché è composto da 6 lettere, ma non ha corrispondenza, come mai? Perché ha una lettera accentata che non rientra nel set di caratteri [a-zA-Z] (che per inciso significa qualunque lettera maiuscola o minuscola).

La soluzione potrebbe essere quella di includere anche un set di caratteri per le lettere accentate, ma direi che possiamo percorrere strade meno caotiche.

I caratteri di una parola

Proviamo a scrivere questa regexp

1\b\w\w\w\w\w\w\b

Funziona! E siccome siete stati bravi fino a qui vi meritate un piccolo trucchetto. Possiamo semplificare la regexp in questo modo:

1\b\w{6}\b
2
3Vale anche per la precedente
4
5\b[a-zAZ]{6}\b

cosa fa esattamente \w?

Come già anticipato \w serve a trovare una corrispondenza con una parola, ma cosa significa? Vediamolo con questo testo:

1!@#$%^&*()_+1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM[]{};’:”,./<>?

Le corrispondenze sono 63 una per ogni lettera maiuscola e minuscola, numero e underscore (quest’ultimo perché viene usato spesso per separare le parole).

\W invece individua tutti i caratteri che possono essere considerati bordo di una parola, quindi individua tutti i caratteri opposti a quelli di \w.

In tutto questo \B che fa?

La differenza tra \b e \B è un pochino più particolare. Se \b ci posiziona nel punto di separazione tra un carattere di fine parole e la parola stessa, \B farà esattamente l’opposto prendendo lettere, numeri e underscore come caratteri di bordo.

In pratica

Se il concetto che ho scritto nel paragrafo precedente allora l’esercizio di questa lezione sarà una passeggiata. Prendiamo in considerazione il seguente testo:

1p11p
2l00l
3b4d455
4pq00pq

Come si individuano i numeri 00?

Se usassimo \w00\w avremmo le due corrispondenze, ma verrebbero prese nelle selezione anche le due lettere limitrofe alla cifra che ci interessa.

Con \b00\b non avremmo nessun risultato perché 00 si colloca sempre tra due lettere e sappiamo che il bordo per \b è tra la lettera e il carattere non lettera, ma quindi questo significa che la situazione contraria fa proprio al caso nostro, quindi la soluzione all’esercizio è \B00\B.

Conclusioni

Con questa lezione abbiamo visto più nel dettaglio le stringhe e abbiamo approfondito il già ben noto \b e il suo gemello contrario \B. Inoltre, abbiamo visto anche \w e \W che ci hanno aiutato a capire ancora meglio il funzionamento degli altri due.

Caricamento...

Diventiamo amici di penna? ✒️

Iscriviti alla newsletter per ricevere una mail ogni paio di settimane con le ultime novità, gli ultimi approfondimenti e gli ultimi corsi gratuiti puubblicati. Ogni tanto potrei scrivere qualcosa di commerciale, ma solo se mi autorizzi, altrimenti non ti disturberò oltre.

Se non ti piace la newsletter ti ricordo la community su Discord, dove puoi chiedere aiuto, fare domande e condividere le tue esperienze (ma soprattutto scambiare due meme con me). Ti aspetto!

Ho in previsione di mandarti una newsletter ogni due settimane e una commerciale quando capita.