In questa lezione della nostra guida Javascript affronteremo un argomento molto importante ovvero come utilizzare le espressioni regolari allโinterno delle nostre applicazioni. La padronanza dei costrutti delle RegExp รจ un requisito fondamentale per il "buon sviluppatore" Javascript in quanto consente, tra le altre cose, di creare strumenti di validazione efficaci con cui verificare la correttezza dei dati passati in input dagli utenti.
Cosa sono le RegExp?
Le regular expressions (in italiano "espressioni regolari") โ comunemente abbreviate in RegExp โ sono un potente strumento per il controllo formale della sintassi di una stringa al fine di verificare che questa corrisponda o meno ad un modello (pattern) predefinito.
Le espressioni regolari sono una tecnica trasversale a quasi tutti i linguaggi di programmazione, tantโรจ che alcuni sono arrivati a definire questa tecnica come uno pseudo-linguaggio vero e proprio.
La definizione di pattern richiede la conoscenza di una sintassi piuttosto complessa, abbastanza familiare, tuttavia, a coloro che conoscono il Perl. Pur avendo tratti comuni a vari linguaggi, le espressioni regolari variano a seconda del linguaggio utilizzato quindi modelli creati per PHP, ad esempio, non funzionano necessariamente in Javascript (seppur vi sia una grande somiglianza).
Casi dโuso frequenti per le RegExp
Un classico esempio di controllo di espressione regolare รจ rappresentato dalla verifica della corretta formattazione sintattica dellโindirizzo email; tale verifica, in estrema sintesi, controlla che lโindirizzo sia composto da una username, seguito dalla chiocciola (@) e dal dominio del sito/provider.
username@dominio.ext
Altro esempio di espressione regolare piuttosto utilizzata riguarda il controllo formale dell codice fiscale: questo รจ composto da 16 caratteri alfanumerici, in una sequenza "predefinita" del tipo:
AAABBB12C21D345E
Ovviamente ci sono molti altri esempi in cui รจ frequente ricorrere alle espressioni regolari per controllare una stringa, normalmente si tratta di esigenze di validazione di informazioni ricevute in input dagli utenti attraverso una querystring o un form.
Dichiarare unโespressione regolare in Javascript
Esistono due sistemi con cui รจ possibile dichiarare il pattern (sequenza di caratteri di controllo) di unโespressione regolare; il primo รจ attraverso una semplice stringa contenuta in una coppia di caratteri slash (/) ed il secondo attraverso lโoggetto RegExp.
La sintassi attraverso la quale definire il pattern per unโespressione regolare รจ la seguente:
var espressione = /pattern/;
Vediamo un esempio di pattern per verificare che una stringa sia composta solo da caratteri alfabetici senza fare distinzione tra maiuscole e minuscole:
var espressione = /^[a-z]+$/i;
Vedremno piรน avanti in che modo รจ stato composto questo pattern, per ora limitiamoci ad osservare come questo sia racchiuso tra i caratteri di slash e che dopo lo slash di chiusura รจ stata aggiunta una "i".
Questa lattera (i) รจ detta modificatore ed indica al nostro programma di effettuare una ricerca NON case sensitive (la "i" sta per ignore case), cioรจ di non fare differenze tra maiuscole e minuscole.
I modificatori supportati sono tre:
- i โ non distingue tra maiuscole e minuscole;
- g โ esegue ricerche globali, cioรจ non si ferma alla prima occorrenza;
- m โ esegue ricerche multiline (il pattern viene confrontato con ogni linea del testo);
Come detto esiste un secondo modo per la creazione di espressioni regolari e consiste nellโutilizzo dellโoggetto RegExp. Questo viene istanziato in una variabile un poโ come accade per lโoggetto Date():
var espressione = new RegExp('pattern');
Volendo riprodurre lโesempio visto sopra avremmo scritto:
var espressione = new RegExp('^[a-z]+$','i');
Come vedete il pattern รจ il primo attributo atteso dal metodo mentre lโeventuale modificatore รจ il secondo.
In sostanza non ci sono differenze tra questi due sistemi dichiarativi. Negli esempi che seguiranno, per semplicitร , utilizzeremo il primo dei due sistemi descritti.
Effettuare un controllo tramite espressione regolare: il metodo test()
Per impostare il controllo di unโespressione regolare si utilizza il metodo test() dellโoggetto RegExp il quale restituirร true in caso di successo o false in caso contrario. Vediamo la sintasi:
if (espressione.test(stringa))
{
// "stringa" รจ conforme all'espressione
}
else
{
// "stringa" NON รจ conforme all'espressione
}
Naturalmente possiamo impostare il controllo in modo inverso attraverso lโoperatore logico di negazione. Se vogliamo che il nostro programma faccia qualcosa solo se lโespressione regolare non รจ verificata scriveremo cosรฌ:
if (!espressione.test(stringa))
{
// avviso dell'errore...
}
il che equivale a:
if (espressione.test(stringa) == false)
{
// avviso dell'errore...
}
Vediamo un esempio concreto: supponiamo di voler verificare che lโusername inserito dallโutente sia composto solo da letteri e numeri avvisandolo (con un alert) in caso di errore:
// definisco in una variabile un username in modo arbitrario
// nella realtร recupereremo questo valore da un campo input di un form
var username = 'mario.rossi';
// imposto un modello
var re = /^[a-z0-9]+$/i;
// faccio la verifica
if (!re.test(username)) {
alert('Puoi inserire solo lettere e numeri!');
}
Estrarre le stringhe corrispondenti al pattern: il metodo exec()
Se il metodo test() restuisce semplicemente true o false, il metodo exec() restuisce la stringa corrispondente al pattern (se trovata) oppure null (in caso di match non riuscito). Vediamo un esempio:
// definisco una stringa
var str = 'Mr.Webmaster';
// definisco un semplice pattern per verificare
// che la stringa inizi per "Mr"
var re = /^Mr/;
var res = re.exec(str);
document.write(res);
Questo esempio stamperร a video: Mr
Costruire il pattern: la sintassi delle espressioni regolari
Veniamo adesso alla parte piรน difficile dellโargomento espressioni regolari, ovvero la definizione dei pattern (sequenze di caratteri di controllo), dei costrutti sintattici e semantici.
Una volta entrati nei vari meccanismi che regolano la definizione di unโespressione regolare, piรน o meno semplice o generica, risulterร molto semplice risolvere problemi apparentemente diffici, risolvibili altrimenti con lunghe routine di controllo attraverso il linguaggio di programmazione o di scripting utilizzato.
Abbiamo giร visto piรน sopra un esempio che verifica che una stringa sia composta esclusivamente da caratteri alfanumerici:
var espressione = /^[a-z0-9]+$/i;
Analizziamo la sintassi utilizzata allโinterno di questa espressione regolare:
- ^ โ indica che la stringa deve iniziare conโฆ;
- [ e ] โ indicano qualsiasi carattere tra quelli al loro interno;
- a-z e 0-9 โ indica che la stringa puรฒ contenere tutti i caratteri che vanno da "a" a "z" e da 0 a 9;
- + โ indica che la stringa deve contenere almeno uno dei caratteri tra le parentesi quadre;
- $ โ indica il termine della stringa;
Ipotiziamo che uno dei caratteri da controllare in unโespressione regolare sia, accidentalmente, un metacarattere delle espressioni regolari o altro carattere speciale (come ad esempio una parentesi quadra). Per farlo utilizzeremo il carattere back-slash (\) per isolarlo. Facciamo un esempio supponendo di dover verificare che una data stringa contenga il carattere "^":
/\^/
Se il carattere da controllare รจ proprio un back-slash, utilizzeremo un doppio back-slash:
/\\/
Il primo back-slash fungerร da literal escape ed il secondo verrร interpretato come carattere semplice e non come speciale.
Passiamo a qualcosa di piรน complesso. Ipotizziamo di voler verificare che in una stringa sia presente il carattere punto che separi due blocchi alfanumerici. Ecco lโespressione regolare da utilizzare:>/p>
var espressione = /^[a-z]+\.[a-z]/;
var stringa = "mrwebmaster.it";
if (!espressione.test(stringa))
{
document.write("La stringa non รจ valida!");
}
Anche in questo caso abbiamo utilizzato un backslash in quanto il carattere punto (.) ha un valore "speciale" nella sintassi delle espressioni regolari e, se non preceduto da un backslash, euqivale a dire "qualsiasi carattere".
Fino ad ora, nei pochi esempi trattati, abbiamo visto alcuni caratteri speciali ma in relatร ne esistono parecchi. Vediamo di seguito un riepilogo dei caratteri speciali, dei metacaratteri e delle strutture sintattiche utilizzati nelle espressioni regolari:
Marcatori di inizio e termine stringa:
- ^ โ verifica lโinizio di una stringa (attenzione! se utilizzato allโinterno di una parentesi quadra indica una negazione);
- $ โ verifica la fine di una stringa;
Metacaratteri:
- . โ qualsiasi carattere ad esclusione del ritorno a capo;
- \w โ verifica che una stringa sia alfanumerica, minuscola
- \W โ verifica che una stringa sia alfanumerica, maiuscola
- \d โ indica qualsiasi cifra numerica;
- \D โ indica qualsiasi carattere che non sia una cifra numerica;
- \s โ indica uno spazio vuoto;
- \S โ indica qualsiasi carattere che non sia uno spazio vuoto;
- \t โ indica una tabulazione;
- \r โ indica un carriage return;
- \n โ indica un linefeed;
Parentesi quadre:
- [โฆ] โ le parentesi quadre identificano range e classi di caratteri;
- [abc] โ identifica qualsiasi carattere tra quelli tra parentesi quadra;
- [^abc] โ identifica qualsiasi carattere ad esclusione di quelli tra quelli tra parentesi quadra (^ funge da negazione);
- [a-z] o [0-9] โ il trattino allโinterno della parentesi quadra identifica un range di caratteri;
Parentesi tonde:
- (โฆ) โ le parentesi tonde identificano dei gruppi di caratteri (i gruppi diventamo fondamentali se si deve effettuare una sostituzione mediante espressioni regolari);
- (a|b) โ il simobolo | identifica un alternanza (o "a" o "b") allโinterno del gruppo;
Ripetizioni di caratteri:
- {x} โ indica il carattere precedente per x volte
- {x,} โ indica il carattere precedente per x o piรน volte
- {x,y} โ il carattere precedente si ripetere x volte ma non piรน di y
- ? โ indica il carattere precedente per 0 o 1 occorrenza
- * โ equivale a {0,}
- + โ equivale a {1,}
RegExp: snippet pronti allโuso
Come detto allโinizio di questo articolo, la scrittura di RegExp non รจ una cosa semplicissima in quanto per poter definire in autonomia dei pattern corretti รจ necessario avere una certa padronanza della materia.
Per questo motivo ritengo utile fornire una serie di modelli pronti allโuso per affrontare i casi piรน frequenti.
Validare un nome
Supponiamo di dover validare un campo di un form in cui lโutente deve inserire il suo nome. Per farlo accetteremo lettere dellโalfabeto (sia minuscole che maiuscole) e spazi (pensiamo ai nomi composti) con una lunghezza minima di 6 caratteri e massima di 30 caratteri:
var nome = /^[A-Za-z ]{6,30}$/;
Validare una password
Per validare una password abbiamo bisogno di costruire un pattern che accetti caratteri alfanumerici (lettere minuscole, maiuscole e numeri) ed imposti una lunghezza minima (ad esempio 8) ed una massima (ad esempio 20):
var password = /^[A-Za-z0-9]{8,20}$/;
Validare un indirizzo di posta elettronica
E terminiamo con il controllo su un indirizzo email, dove รจ consentita la "@", il "-", lโunderscore e il punto, ma nessun altro carattere speciale:
var email = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
Validare una URL
Un altro interessante pattern รจ quello per validare le URL, eccolo:
var url = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
Usare le espressioni regolari per effettuare ricerche e sostituzioni
Attraverso le espressioni regolari รจ possibile utilizzare anche i metodi search() e replace() tipici delle stringhe. Nella lezione successiva vedremo, appunto, come manipolare le stringhe attraverso i metodi e le proprietร ad esse associate.