Chi ha avuto la necessità di dover sviluppare programmi per manipolare testi avrà avuto modo di apprezzare la potenza e la flessibilità delle espressioni regolari.
Questo strumento è allo stesso tempo gioia e dolore per lo sviluppatore che deve individuare stringhe in un testo o sostituire parti di testo con altro o verificare che un testo segua un formato specifico.
Gioia perchè la potenza delle espressioni regolari è tale da lasciare talvolta sbalorditi; dolore perchè la loro sintassi è un po' criptica e, come se non bastasse, l'esistenza di alcune varianti generano un bel po' di confusione.
Una delle applicazioni più interessanti è legata al riconoscimento di linguaggi che fanno uso di markup come documenti XML e pagine HTML, o di formati per lo scambio di informazioni basati su stringhe come JSON. Così come si può riconoscere e manipolare il formato di un intero file di testo, è possibile verificare che una semplice stringa realizzi un certo formato (ad esempio la data o l'e-mail)
Per i programmatori PERL le espressioni regolari sono il pane quotidiano. Per buona parte dei programmatori JavaScript, invece, questo strumento è poco noto, se non addirittura ignorato. Eppure JavaScript ha un supporto nativo delle espressioni regolari che consente di fare alcune comuni elaborazioni in modo elegante ed efficiente.
Espressioni regolari
Le espressioni regolari sono schemi (o pattern) che descrivono sinteticamente un insieme di stringhe utilizzando specifici caratteri speciali detti metacaratteri. Avete presente i caratteri jolly del DOS? Quelli che servono per indicare un insieme di nomi di file, come ad esempio *.html
per indicare tutti i file che hanno estensione .html? Ecco, questi non sono che un piccolissimo esempio di qualcosa di simile alle espressioni regolari. Diciamo innanzitutto che ciascun carattere e ciascun numero rappresenta se stesso. Quindi, ad esempio, l'espressione regolare test rappresenta proprio la stringa test.
I metacaratteri più usati sono rappresentanti dal punto (.), che indica un qualsiasi carattere singolo, l'asterisco (*), che indica la presenza di zero o più occorrenze del carattere precedente, il simbolo +, che indica la presenza di una o più occorrenze del carattere precedente, il punto interrogativo (?), che indica la presenza di zero o una occorrenza del carattere precedente.
La seguente tabella riepiloga i metacaratteri fondamentali riportando una sintetica descrizione e un semplice esempio:
Metacarattere | Descrizione | Esempio |
---|---|---|
. | Indica un qualsiasi singolo carattere | L'espressione t.st
t
st
|
* | Indica la presenza di zero o più occorrenze del carattere o dell'espressione che lo precede. | L'espressione t*est
t
est
|
+ | Indica la presenza di una o più occorrenze del carattere o dell'espressione che lo precede. | L'espressione t+est
t
est
|
? | Indica la presenza di zero o una occorrenza del carattere o dell'espressione che lo precede. | L'espressione t?est
est
test
|
{n} | Indica la presenza di n occorrenze del carattere o dell'espressione che lo precede. | L'espressione te{2}st
teest
|
{m, n} | Indica la presenza di almeno m
n
|
L'espressione te{2, 4}st
teest
teeest
teeeest
|
$ | Indica la fine di una linea. | L'espressione test$
test
|
^ | Indica l'inizio di una linea | L'espressione ^test
test
|
[] | Indica un qualsiasi singolo carattere contenuto all'interno delle parentesi quadre. | L'espressione t[ea]st
test
tast
|
[^] | Indica un qualsiasi singolo carattere tranne quelli contenuti all'interno delle parentesi quadre. | L'espressione t[^iu]st
t
st
tist
tust
|
[c1-c2] | Indica un intervallo di caratteri compresi tra c1 e c2 | L'espressione [r-t]est
rest
sest
test
|
[^c1-c2] | Indica un qualsiasi singolo carattere tranne quelli compresi tra c1 e c2. | L'espressione t[^a-c]st
t
st
tast
tbst
tcst
|
( ) | Consente di raggruppare sottoespressioni a cui applicare metacaratteri | L'espressione (te)+st
te
st
test
tetest
tetetest
|
| | Indica l'alternativa tra due o più caratteri o espressioni. | L'espressione t(es|oas|u)t
test
toast
tut
|
Indica che il carattere seguente deve essere trattato come un normale carattere e non come un metacarattere | L'espressione te*st
te*st
|
Seguendo il significato dei metacaratteri indicato nella tabella, proviamo a leggere la seguente espressione:
[a-zA-Z]{6}[0-9]{2}[a-zA-Z][0-9]{2}[a-zA-Z][0-9]{3}[a-zA-Z]
Essa indica una sequenza di sei caratteri alfabetici, seguita da due caratteri numerici, una lettera, due numeri, una lettera, tre numeri ed infine una lettera. Vi ricorda qualcosa? E' lo schema di un codice fiscale.
Stringhe ed espressioni regolari
Visti gli elementi di base della sintassi delle espressioni regolari, vediamo come utilizzarle con JavaScript. Il modo più semplice consiste nell'utilizzare alcuni metodi delle stringhe. Ad esempio, il metodo search() verifica l'esistenza di una stringa che appartiene all'insieme individuato dall'espressione regolare passata come parametro. Consideriamo le seguenti istruzioni:
var pattern = /[a-zA-Z]{6}[0-9]{2}[a-zA-Z][0-9]{2}[a-zA-Z][0-9]{3}[a-zA-Z]/
var stringa = "Il codice fiscale di Mario Rossi: RSSMRA70A01H501S"
var result = stringa.search(pattern)
La prima riga assegna alla variabile pattern l'espressione regolare che specifica un codice fiscale; da notare che l'espressione regolare deve essere racchiusa tra due caratteri slash (/). La seconda riga assegna alla variabile stringa una sequenza di caratteri contenente il codice fiscale del signor Mario Rossi. La terza ed ultima riga esegue il metodo search() mettendo nella variabile result il risultato. La variabile conterrà il valore 34, cioè l'indice all'interno della stringa a partire dal quale è stata individuata la sottostringa che combacia con l'espressione regolare. Nel caso non venga trovata una sottostringa corrispondente, il metodo search() restituisce il valore ǃ.
Gli altri metodi che consentono di lavorare con le espressioni regolari sono:
- match(espr):
- replace(espr, testo):
- split(espr):
L'oggetto RegExp
L'approccio appena visto per definire espressioni regolari è basato sui cosiddetti letterali (literal), nome dato alle espressioni regolari delimitate dagli slash. JavaScript prevede anche un modo alternativo per creare espressioni regolari, che fa uso dell'oggetto RegExp. Utilizzando questo approccio, le istruzioni viste nell'esempio basato sui letterali diventa come di seguito mostrato:
var pattern = new RegExp("[a-zA-Z]{6}[0-9]{2}[a-zA-Z][0-9]{2}[a-zA-Z][0-9]{3}[a-zA-Z]")
var stringa = "Il codice fiscale di Mario Rossi: RSSMRA70A01H501S"
var result = stringa.search(pattern)
Come potete vedere, non ci sono poi grosse differenze con l'approccio visto prima. Perchè utilizzare allora questo secondo approccio? Uno dei motivi potrebbe essere la possibilità di creare le espressioni regolari dinamicamente. Infatti, mentre con l'approccio letterale l'espressione regolare è fissa e deve essere nota quando si scrive lo script, tramite l'oggetto RegExp possiamo generare l'espressione dinamicamente, costruendo al volo la stringa che rappresenta l'espressione regolare.
Indipendentemente dall'approccio utilizzato, l'istanza dell'espressione regolare mette a disposizione i seguenti metodi:
- test(testo):
- exec(testo):
Qualche esempio
L'uso tipico delle espressioni regolari in JavaScript è nella convalida dell'input. Ad esempio, se dobbiamo verificare che il dato inserito in una casella di testo di una form segua lo schema di un codice fiscale, possiamo associare la seguente funzione all'evento click del pulsante di invio:
Listato 1. Esempio di utilizzo di espressioni regolari per la convalida di un input
function convalida() {
var pattern = /^[a-zA-Z]{6}[0-9]{2}[a-zA-Z][0-9]{2}[a-zA-Z][0-9]{3}[a-zA-Z]$/;
var txtCodiceFiscale = document.getElementById("CodiceFiscale");
if (txtCodiceFiscale.value.search(pattern) == -1) {
alert("Il valore inserito non è un codice fiscale!");
txtCodiceFiscale.focus();
} else {
document.form[0].submit()
}
}
Da notare come l'espressione regolare in questo esempio riporta il simbolo iniziale ^ e il simbolo finale $, che ci assicurano indirettamente che il dato da convalidare corrisponda esattamente all'intera stringa e non ad una sua sottostringa.
Un altro esempio d'uso può essere la sostituzione di caratteri speciali, come ad esempio < e >, con le relative entità HTML all'interno di una textarea:
Listato 2. Convertire caratteri speciali in entità
function ConvertiInEntita(testo){
var pattern = /</;
var temp = testo.replace(pattern, '<');
pattern = />/;
return temp.replace(pattern, '<');
}
Quelli mostrati non sono che dei semplici esempi di applicazione delle espressioni regolari con script JavaScript. Numerose sono le possibili altre applicazioni che lasciamo all'inventiva del lettore.
Conclusioni
Abbiamo visto in questo articolo come utilizzare le espressioni regolari negli script JavaScript. Abbiamo mostrato alcuni semplici esempi di utilizzo, ma le potenzialità sono davvero enormi.
Per qualche spunto interessante è possibile consultare un elenco di espressioni regolari di uso più o meno comune.
Altra risorsa molto utile può essere il software Expresso, che è valido aiuto per costruire e testare le espressioni regolari che ci occorrono.