Homa Page di Daniele Franceschini
Introduzione alle espressioni regolari
Va precisato subito che l’argomento espressioni regolari non è immediato da capire, per cui è necessario un po’ di pazienza e di esercizio per avere un minimo di dimestichezza con questo potente strumento.
In Javascript l’oggetto che si occupa di gestire l’espressioni regolari è RegExp.
La creazione di un’espressione regolare avviene sia attraverso il costruttore RegExp() sia attraverso un letterale stringa dotato di una sintassi particolare.
La sintassi per il letterale stringa è la seguente:
var patter = /s$/;
La riga sopra crea un nuovo oggetto RegExp e lo assegna alla variabile patter, nel caso specifico l’oggetto indica una qualsiasi stringa che termina con”$”
Comunque prima di iniziare a maneggiare le espressioni regolari, è necessario avere ben presente alcune regole che possiamo riepilogare in questo elenco:
- Caratteri letterali
- Classi carattere
- Ripetizione
- Alternanza, raggruppamento e riferimenti
- Specificazione della posizione di coincidenza
- Gli attributi
Caratteri Letterali
Nelle espressioni regolari tutti i caratteri vengono confrontati fra loro, tuttavia non tutti i caratteri sono visibili, per esempio il carattere che specifica una nuova riga oppure il carattere di tabulazione. Inoltre ci sono alcuni caratteri che sono utilizzati proprio dalle regole delle espressioni regolari, pertanto per poter fare riferimento a questi caratteri senza scontrarci con il linguaggio delle espressioni regolari è necessario vedere come questi caratteri possono essere rappresentati all’interno di una espressione.
La tabella sottostante elenca i caratteri letterali come devono essere scritti all’interno di una espressione.
| Carattere | Coincidenza |
|---|---|
| \f | Form feed avanzamento foglio |
| \n | Nuova riga |
| \r | Ritorno a capo |
| \t | Tabulazione |
| \v | Tabulazione verticale |
| \/ | / letterale |
| \\ | \ letterale |
| \* | * letterale |
| \+ | + letterale |
| \. | . letterale |
| \? | ? letterale |
| \| | | letterale |
| \( | ( letterale |
| \) | ) letterale |
| \[ | [ letterale |
| \] | ] letterale |
| \{ | { letterale |
| \} | } letterale |
| \xxx. | Carattere ASCII specificato dal numero ottale xxx. |
| \xnn | Carattere ASCII specificato dal numero esadecimanle nn |
| \cX | } Carattere di controllo ^X |
Classi carattere
Le classi carattere sono un insieme di caratteri racchiusi fra parentesi quadre. Una classe carattere coincide con ogni carattere in essa contenuto, inoltre è possibile definire delle classi carattere esclusive ossia: coincidono con qualsiasi carattere esclusi quelli presenti tra le parentesi. Una classe carattere esclusiva si specifica attraverso un accento circonflesso come primo carattere dopo la prima parentesi quadra, pertanto se si scrive
/[^abc]/
si sta dicendo che si desidera che vengano rilevate le corrispondenze di qualsiasi carattere ad esclusione di “a”,”b”,”c”.
Un’altra funzione utile è quella di specificare un intervallo di caratteri, per ottenere questo risultato basta utilizzare il carattere trattino “-” esempio:
/[a-z]/
La regola alla precedente riga indica tutti i caratteri minuscoli dalla a alla z
Per individuare un qualsiasi carattere alfanumerico la regola sarebbe:
/[a-zA-Z0-9]/
Visto che alcune classi carattere sono di utilizzo comune, in javascript ci sono alcuni caratteri speciali e sequenze di escape per rappresentare queste classi comuni, sotto riporto l’elenco.
| Carattere | Coincidenza |
|---|---|
| [...] | Qualsiasi carattere fra parentesi |
| [^...] | Qualsiasi carattere non racchiuso tra le parentesi |
| . | Qualsiasi carattere accettuato nuova riga. Equivalente a [^\n] |
| \w | Qualsiasi carattere alfanumerico. Equivalente a [a-zA-Z0-9_] |
| \W | Qualsiasi carattere non alfanumerico. Equivalente a [^a-zA-Z0-9_] |
| \s | Qualsiasi carattere di spazio vuoto. Equivalente a [\t\n\r\f\v] |
| \S | Qualsiasi carattere non di spazio vuoto. Equivalente a [^\t\n\r\f\v] |
| \d | Qualsiasi cifra. Equivalente a [0-9] |
| \D | Qualsiasi carattere diverso da una cifra. Equivalente a [^0-9] |
| [\b] | Baclspace letterale |
Ripetizione
Nelle espressioni regolari è possibile anche specificare quante volte un elemento di una espressione può essere ripetuto. La sintassi è la segunete:
{n,m}
il parametro “m” è opzionale è può essere ommesso qualora si ricerchi una esatta corrispondenza ad esempio:
/\w{3}\d?/ //Coincide con 3 caratteri alfanumerici e una cifra opzionale
Anche in questo caso esistono una serie di ripetizioni comuni pertanto il linguaggio javascript prevede dei caratteri speciali che riepilogo sotto:
| Carattere | Coincidenze |
|---|---|
| {n,m} | Coincide con l’oggetto precedente almeno n volte ma non più di m volte |
| {n,} | Coincide con l’oggetto precedente per n volte |
| {n} | Concide con l’oggetto precedente per n o più volte |
| ? | Coincide con l’oggetto precedente per 0 o 1 volta. Equivale a {0,1} |
| + | Coincide con l’oggetto precedente per una o più volte. Equivale a {1,} |
| * | Coincide con l’oggetto precedente per 0 o più volte. Equivale a {0,} |
Alternanza,raggruppamento e riferimenti
Nella grammatica delle espressioni regolari è previsto anche caratteri speciali per la specificazione di alternative, per il raggruppamento delle sottoespressioni o per il riferiemnto a sottoespressioni precedenti. Il carattere che separa le possibili alternative e “|”. Faccio un esempio:
/ab|cd|ef/ //Coincide con le stringa “ab” o “cd” o”ef”
/\d{3}|[a-z]{5}/ //Coincide con 3 cifre o 5 caratteri alfanumerici minuscoli
Il raggruppamento invece si ottiene con l’ausilio delle parentesi tonde, faccio un esempio per semplificare la questione:
/cassa(panca)?/ // Coincide con la stringa “cassa” seguito dalla stringa facoltativa “panca”
Il riferimento viene sempre svolto nei confronti una sottoespressione tra parentesi tonde e permette di fare un riferimento all’indietro a una sottoespressione in un passaggio successivo della stessa espressione. Per fare un riferimento si fa seguire al carattere \ una cifra che fa riferiemento alla sottoespressione. Ecco il solito esempio:
/([‘“])[^’”]*\1
Quindi la sequenza \1 coincide con qualsiasi cosa che coincide con la prima sottoespressione, in parole più semplici: cerca tutte le stringhe che iniziano con apice o doppio apice e un qualsiasi carattere diverso da apice e doppio apice e nuovamente per riferimento cerca ancora un apice o un doppio apice.
Riepilogando ancora:
| Carattere | Significato |
|---|---|
| | | Alternanza. Coincide con le sottoespressioni di sinistra o di destra |
| (...) | Raggruppamento di più oggetti in una singola unità. Memorizza i caratteri che coincidono con il gruppo per l’utilizzo con riferimenti successivi |
| \n | Riferimento al gruppo specificato. I gruppi sono sottoespressioni tra parentesi. I numeri di gruppo sono assegnati contando le parentesi sinistre da sinistra a destra |
Specificazione della posizione di coincidenza
Nelle espressioni regolari alcuni caratteri indicano la posizione di coincidenza, questi caratteri sono indispensabili per intraprendere alcune ricerche come per esempio partendo l’inizio di una stringa, di una nuova riga o di una parola, pertanto questi caratteri ci danno la possibilità di indicare la posizione di coincidenza. Sotto la solita tabella riepilogativa:
| Carattere | Significato |
|---|---|
| ^ | Coincide con l’inizio della stringa. Nelle ricerche su più riga indica l’inizio di una riga |
| $ | Coincide con la fine della stringa o della riga |
| \b | Coincide con l’estremità di una parola |
| \B | Indica una posizione che non rappresenta il limite di una parola |
Attributi
Infine, nella grammatica delle espressioni regolari come ultimo elemento si trovano gli atributi. A differenza degli altri elementi sintattici, gli atributi vengono specificati al di fuori dei carattei “/”, esattamente dopo l’ultima “/”. Gli attributi supportati da jascript sono due: “i” e “g”
| Carattere | Significato |
|---|---|
| i | Confronto non sensibile a maiuscole o minuscole |
| g | Confronto globale, individua tutte le occorenze senza fermarsi dopo la prima |
Nota
Alfine di regolare il confronto dei pattern è necessario sapere che se vogliamo che il confronto venga realizzato su righe multiple, deve essere impostata la proprietà multiline:
RegEx.multiline = true;
Quando le espressioni regolari sono richiamate da un oggetto TextArea, javascript imposta automaticamente questa proprietà a “true” e rimette a “false” la proprietà appena la chiamata è terminata.
Sporchiamoci un po’ le mani, ma solo un po’.
Metodi di una stringa per il confronto dei pattern
Sono previsti 4 metodi per l’utilizzo delle espressioni regolari sulle stringhe:
1. search()
2. replace()
3. match()
4. split()
search()
Richiede come argomento un’espressione regolare e restituisce la posizione del carattere iniziale della prima sottostringa coincidente. Se non trova niente restituisce -1. Non supporta le ricerche globali ignorando l’argomento “g” se passato come attributo.
replace()
Effettua una ricerca e una sostrituzione, il primo argomento di questo metodo è una espressione regolare, il secondo è la stringa di sostituzione.
alert("Javascript javascript javaScript jaVaScriPt".replace(/javascript/gi, "Javascript"));
match()
Richiede come argomento un espressione regolare e restituisce un array contenente i risultati del confronto.
“1 più 2 è uguale a 3”.match(/\d+/g) //restituisce il seguente array [“1”, ”2”, ”3”]
Un altro po’ di esempi:
Ricerca di stringhe semplici
var pattern = /.i/g //faccio una ricerca globale di tutte le “i” precedute da un
//qualsiasi altro carattere
var str = "Ricerca di stringhe semplici";<br />alert(str.match(pattern)); //restituisce “Ri,di,ri,li,ci”<br /><br />var pattern = /..i/g //faccio una ricerca globale di tutte le “i” precedute da due<br />//qualsiasi caratteri<br />alert(str.match(pattern)); //restituisce " di,tri,pli", viene restituito anche la stringa “ di”
//in quanto viene considerato
//anche lo spazio
var pattern = /\w.i/g //faccio una ricerca globale di tutte le “i” precedute da due
//qualsiasi caratteri
alert(str.match(pattern)); //restituisce "tri,pli", in questo modo elimino le occorrenze
//precedute da uno spazio
var pattern = /\d\d.\d\d.\d\d\d\d/g //ricerco solo cifre nel formato indicato per estrarre la data
var str = "Io sono nato il 22-12-1980";<br />alert(str.match(pattern));<br /><br />var pattern = /\D+[^0-9-/]/g //ricerco solo caratteri escludendo tutte le cifra<br />var str = "Io sono nato il 22-12-1980";<br />alert(str.match(pattern));<br /><br />var pattern = /\s/g //ricerco tutti gli spazi<br />var str = "Io sono nato il 22-12-1980";<br />alert(str.replace(pattern,"_")); //sostituisco tutti gli spazzi con il carattere “_”<br /><br />var pattern = /^\s+|\s+$/g //scludo tutti gli spazi agli estrmi della stringa,<br />//potrebbe essere usato in una <br />//funzione trim() che per javascript non esiste<br />var str = " Io sono nato il 22-12-1980 ";<br />alert(str.replace(pattern,""));<br /><br />var pattern = /\S\w+/g //seleziono tutte le parole escludendo gli spazzi<br />var str = " Io sono nato il 22-12-1980 ";<br />alert(str.match(pattern))<br /><br />var pattern = /Daniele/g //trova solo il primo nome<br />var str = "Daniele daniele";<br />alert(str.match(pattern))<br /><br />var pattern = /[Dd]aniele/g //adesso trova anche il secondo<br />alert(str.match(pattern))<br /><br />//seleziono solo le cifre dispari<br />var pattern = /[13579]/g<br />var str = "Le prime dieci cifre sono 0123456789";<br /><br />document.write(str + "<br />");<br />//devo richiamare il metodo join sull'array restituito dal metodo match<br />//per togliere le virgole che separano le cifre<br />document.write("ma io preferisco le cifre dispari " + str.match(pattern).join(""));
//non seleziono le cifre dispari, l'espressione poteva essere scritta in modo
//più semplice ma volevo utilizzare
//l'operatore di negazione per fare un po' più esercizio
var pattern = /[^a-zA-Z13579]/g
document.write("<br />");
var s = "anzi no, adesso preferisco le cifre pari " + str.match(pattern).join("");
document.write(s);
A questo punto si dovrebbe iniziare a intravedere le grandi potenzialità delle espressioni regolari per cui non resta che intraprendere un percorso fatto di pazienza ed esercizio. La validità delle espressioni regolari è dimostrata dal fatto che sono state realizzate oltre 40 anni fa e ancora oggi resistono alle frenetiche evoluzioni dell’informatica. Colui che le ha implementate per la prima volta è uno dei padri dei primi sistemi unix ossia: Ken Thompson. Le cose fatte bene raramente cambiano in modo radicale nel tempo. Costruisci sempre su fondamenta solide.
Se questo articolo ti è interessato forse ti interessa anche questo:
Emulare le funzioni Trim LTrim e RTrim con le espressioni regolari.



