Una breve introduzione al John Wick delle stringhe
Le espressioni regolari sono estremamente utilizzate e terribilmente confusionarie. Con l’esperienza, prendendoci la mano, rimarranno solo terribilmente confusionarie.
Le RegExp (termine tecnico) sanno essere ragazze veramente difficili da gestire: problema difficile da risolvere, difficoltà maggiori da controllare. Eppure talvolta si rilevano essere l’approccio più veloce, simpatico e soprattutto “pulito”. Fare la loro conoscenza — il che non significa risolvere ogni problemi con esse, anzi — ci rende dei programmatori più vissuti.
Non sono un’esclusiva di Javascript. Ciò non ci interessa, in questo articolo andremo a vedere proprio come utilizzarle con il linguaggio web più in voga del momento.
“Avete mai sentito l’arcaica espressione trovare un ago nel pagliaio? Sembra essere vecchia di 500 anni. Le espressioni regolari servono proprio a questo: tu indichi il pagliaio, che cosa trovare e loro lo trovano… a dir il vero fanno anche di più: separano l’ago dal pagliaio e, con esso, anche ogni singolo filo di paglia.”
Signori, tra le mani abbiamo forse il tool più potente per processare e ispezionare stringhe di testo, caratteri alfanumerici, numeri, simboli e lettere senza senso. Sono tra i giocattoli dei grandi, e i piccoli sviluppatori — come me — non dovrebbero toccarli. Anche questo non sembra interessarci, andiamo a sporcarci le mani!
Le espressioni regolari, come quasi ogni cosa in JS, sono di tipo Object e possono essere richiamate in due modi: usando il costruttore RegExp; oppure servendoci dei slash di apertura e di chiusura:
let xyz= new RegExp(“xyz”);
let xyz = /xyz/;
L’uno o l’altro caso significa esclusivamente: questa variabile xyz è un’espressione regolare ‘xyz’. Quindi una lettera x seguita da una y a suo volta seguita da una z. Niente più, niente meno. Se andassimo ad aprire la console del nostro browser preferito e scrivessimo:
console.log(/xyz/.test(“Che sciocchezza le espressioni regolari”));
scopriremo che il risultato che ne verrà fuori sarà ineluttabilmente False.
Possiamo “risolvere il problema” studiando un po di più, o cambiando la stringa: le espressioni regolari non sono affatto facili, dice Mr. xyz — provate su — la nuova stringa passata come parametro della funzione test, prevede la presenza della nostra espressione ricercata, appunto xyz, sarà costretta a restituire un bel True.
test è il metodo più comune: accetta una frase come parametro e restituisce un tipo Boolean. Se la stringa inserita è presente nella nostra frase restituisce un altro bel True.
Per ostacolare ancor più la comprensione, con “stringa” mi riferisco all'espressione regolare e con “frase” alla stringa nella quale andremo a effettuare la ricerca.
/iron/.test(“Guarda c’è ironman!”));
True
Ma metodi per stringhe indexOf e includes svolgono praticamente lo stesso compito di questo metodo per le espressioni regolari, test. Ma fidatevi di Mr. xyz, e portate un po di pazienza: di fatto, per compiti tanto semplici, non si ricorre alle regexp. Le cose cambiano invece quando dobbiamo cercare un insieme di caratteri alfanumerici non ben definiti, seguiti magari da strani simboli alieni… Vediamo qualche esempio.
/\D[0–5][6–9]\D/.test(“Ho appena compiuto 27 anni”);
True
La seguente espressione si può leggere in questo modo: dentro la frase “Ho appena compiuto 27 anni” è presente l’espressione \D[0–5][6–9]\D:
\D sta per “qualsiasi carattere che non sia un numero
[0–4] sta per “qualsiasi numero compreso tra 0 e 4, non ripetuto
[5–9] stessa cosa per sopra ma tra 5 e 9
\D sta nuovamente per “qualsiasi carattere che non sia un numero”
Analizzando nuovamente con comprendonio la nostra frase vedremo adesso che ho appena compiuto è un insieme di caratteri alfabetici e nessun numero, e che quindi rispetta la definizione \D;
27 sono due numeri, precisamente il 2 e il 7, non ripetuti, ove il primo è compreso tra 0–4 e il secondo è compreso tra 5–9;
infine anni sono tutti caratteri alfabetici e nessun numero, rispetta anch'esso \D.
Da notare come la **built-in-shortcut* \D accetta più di un carattere o la ripetizione delle stesso o ancora la presenza di uno spazio o di qualsiasi altra cosa che non sia un numero. Mentre la scorciatoia tra parentesi quadre, che abbiamo adottato per la gestione dei numeri interi da 0 a 4, prevede un solo numero, per l’appunto, compreso tra 0 e 4, inclusi.*
Lista built-in-shortcut:
\d Solo numeri
\w Sia numeri che caratteri alfabetici
\s Qualsiasi spazio vuoto, tabulazione, linea a capo, et similia
\D Solo caratteri alfabetici
\W Solo simboli
\S Qualsiasi elemento eccezion fatta per gli spazi vuoti, tab, et
similia
. Qualsiasi carattere, numero, simbolo e spazio, eccezion fatta
per il ritorno a capo
Data la tabella sopra, e la breve introduzione all'uso delle parentesi quadre, proviamo ad analizzare un esempio pratico, talvolta anche utile, ma al momento… cosa?!?:
/^[A-Z]{6}\d{2}\D\d{2}\D\d{3}\D$/
L’espressione soprastante, rullo di tamburi, va a verificare se la frase inserita è un codice fiscale valido. Capisco che ci sono simboli sconosciuti che ancora non sono stati trattati e certamente destano non poche perplessità. Ma avete scelto voi di imparare a programmare, tenetelo a mente; episodi come questo sono frequenti!:
^ Identifica l’inizio dell’espressione
[A-Z] Tutte le parole dalla A alla Z
{6} Identifica il numero di volte che verrà ripetuto
l’elemento precedente (nel caso [A-Z])
\d Identifica un numero (già visto)
{2} Nuovamente identifica il numero di volte, in questo caso
dell’elemento \d
\w Identifica un carattere
... e così via, fino a
$ che identifica la fine dell’espressione
Quindi proviamo a inserire il nostro codice fiscale sulla console e vediamo un po se per il nostro computer siamo tipi True o False.
test non è l’unico metodo a disposizione per la gestione delle espressioni. Diamo una veloce occhiata anche al metodo replace, che sostituisce parti di una stringa, e al metodo exec, che ci restituisce l’indice di riferimento di una porzione di stringa.
Il metodo replace, come suggerisce il nome, rimpiazza una porzione della nostra frase con un’altra.
“Ironman”.replace(“man”, “woman”);
Mentre il metodo exec restituisce un oggetto contenente — tra l’altro — l’indice di riferimento della porzione di stringa ricercata.
/\d/.exec(“uno è diverso da 1”);
Concludiamo in bellezza con un bel sommario semplice e conciso, rubato direttamente da Eloquent Javascript:
/xyz/ La sequenza di caratteri ‘xyz’
/[xyz]/ Almeno uno tra ‘x’ o ‘y’ o ‘z’
/[^xyz]/ Qualunque carattere eccetto la sequenza
‘xyz’
/[0–9]/ Qualunque numero compreso tra 0 e 9
/z+/ Una o più occorrenze del carattere ‘z’
/z*/ Zero o più occorrenze del carattere ‘z’
/z?/ Zero o una occorrenza del carattere ‘z’
/z{2,4}/ Da due a quattro occorrenza del carattere
‘z’
/(xyz)/ Il gruppo della sequenza ‘xyz’
/x|y|z/ Almeno uno tra ‘x’ o ‘y’ o ‘z’
/\d/ Solo numeri
/\w/ Sia numeri che caratteri alfabetici
/\s/ Qualsiasi spazio vuoto, tabulazione, linea a
capo, et
similia
/\D/ Solo caratteri alfabetici
/\W/ Solo simboli
/\S/ Qualsiasi elemento eccezion fatta per gli
spazi vuoti, tab, et similia
/./ Qualsiasi carattere, numero, simbolo e
spazio, eccezione il ritorno a capo
/^/ Inizio
/$/ Fine
A questo punto spero proprio di non aver esagerato, e vi auguro di trovare tutti gli aghi in tutti i vostri pagliai!
Buona programmazione!
Top comments (3)
I dont understand anything since this is written in italian:-(
Hi ProMike, English version !!
howtoreadcode.com/regular-expressi...
Thanks:-)