Espressione regolare
Una espressione regolare (in inglese regular expression o, in forma abbreviata, regexp, regex o RE) è una sequenza di simboli (quindi una stringa) che identifica un insieme di stringhe. Programmi diversi supportano notazioni diverse per esprimere le stesse espressioni regolari, nel senso che non esiste una sintassi "universale".
Le espressioni regolari sono generalmente usate per definire linguaggi regolari, tuttavia permettono di definire anche linguaggi non regolari. I linguaggi regolari sono i linguaggi generati da grammatiche di tipo 3 (nella gerarchia di Chomsky) e riconosciute da automi a stati finiti.
Indice |
[modifica] Definizione
Una espressione regolare definisce una funzione che prende in ingresso una stringa, e restituisce in uscita un valore del tipo sì/no, a seconda che la stringa segua o meno un certo pattern.
Ad esempio, tutti gli indirizzi e-mail devono essere costituiti nel seguente modo: cominciare con una sequenza di caratteri alfanumerici, seguiti dal simbolo chiocciola, seguiti da altri caratteri alfanumerici, seguiti dal punto, seguiti da due o tre lettere.[1] Questa regola informale diventerebbe una regex qualora fosse codificata secondo una sintassi ben precisa e riconosciuta da un programma in grado di analizzare le stringhe.
[modifica] Storia
Sebbene fossero state formalizzate già fin dagli anni quaranta, le espressioni regolari entrarono nel mondo informatico per la prima volta alla fine degli anni sessanta, in ambiente Unix: il primo editor di testo che implementava delle funzioni che ne permettessero l'uso fu una versione di QED scritta da Ken Thompson, uno dei pionieri di Unix.
L'editor, dalla sua interfaccia a riga di comando, metteva a disposizione un comando chiamato global regular expression print, che successivamente fu reso un applicativo indipendente, grep.
Le espressioni regolari non ebbero grande diffusione ed utilizzo fino agli anni ottanta, quando fu inventato il linguaggio di programmazione Perl che permetteva nativamente l'uso di espressioni regolari. La versatilità del linguaggio, dovuta anche al fatto d'essere un linguaggio interpretato, ne permise l'utilizzo in svariate situazioni e favorì lo sviluppo del formalismo di Perl per le espressioni regolari, che diventò uno standard de facto.
La grandissima diffusione di questi strumenti spinse alcuni sviluppatori a implementare le espressioni regolari anche in altri linguaggi, a mezzo di librerie come PCRE o persino come parte delle librerie standard di alcuni linguaggi, come Java e tcl.
Attualmente le espressioni regolari sono disponibili nella maggioranza degli editor di testo per GNU/Linux e altri sistemi unix-like.
[modifica] Espressioni regolari nei linguaggi formali
Le espressioni regolari sono composte da costanti e operatori che denotano insiemi di stringhe, e da operazioni tra questi insiemi.
Dato un alfabeto finito Σ, sono definite le seguenti costanti:
o
(insieme vuoto)
(stringa vuota, ovvero la stringa di lunghezza 0)
(carattere,
)
e le seguenti operazioni:
- concatenazione: RS o
indica l'insieme 
- unione:
indica l'unione dei due insiemi - stella di Kleene: R * indica l'insieme che contiene tutte le possibili iterazioni ottenibili dagli elementi di R
- intersezione:
indica l'intersezione tra i due insiemi di stringhe - complemento: il complementare di R indica l'insieme delle stringhe appartenenti a

Ad esempio dati
e
,
e 
Allora, possiamo dire che un'espressione regolare, definita a partire da un alfabeto Σ ed un insieme di simboli
, è una stringa
che rende vera alcuna delle seguenti condizioni:


- R = S + T o R = ST o R = S * , dove S e T sono espressioni regolari sull'alfabeto Σ
[modifica] Impiego delle espressioni regolari
Le espressioni regolari sono utilizzate principalmente da editor di testo per la ricerca e la sostituzione di porzioni del testo. Grande importanza rivestono inoltre nell'informatica teorica, nella quale, ad esempio, sono utilizzate per rappresentare tutti i possibili cammini su un grafo. Tuttavia, le espressioni regolari sono adatte a rappresentare un ristrettissimo insieme di linguaggi formali (se volessimo rappresentare espressioni aritmetiche o linguaggi di programmazione, avremmo già bisogno di utilizzare linguaggi di tipo 2): l'utilizzo dei linguaggi regolari è comunque conveniente, in quanto la chiusura degli stessi alle operazioni di unione, intersezione e complementazione, permettono la costruzione di un'algebra di Boole ed una buona capacità decisionale.
[modifica] Sintassi
[modifica] Espressioni regolari tradizionali di UNIX
La sintassi di base delle espressioni regolari in UNIX è attualmente definita obsoleta dallo standard POSIX, ma è comunque molto usata a causa della sua diffusione. La maggior parte dei programmi che utilizzano le regexp, come grep e sed, utilizzano tali regole di base fornendo al contempo supporto per le nuove regole estese.
In questa sintassi, la maggior parte dei caratteri sono visti come letterali, e trovano solo se stessi ("a" trova "a", "bc)" trova "bc)" ecc.). Le eccezioni a questa regola sono i metacaratteri:
| . | Trova un singolo carattere (se è nella modalità linea singola altrimenti se è in multiriga prende tutti i caratteri diversi da \n, ovvero un ritorno a capo). |
| [ ] | Trova un singolo carattere contenuto nelle parentesi. Ad esempio, [abc] trova o una "a", "b", o "c". [a-z] è un intervallo e trova ogni lettera minuscola dell'alfabeto. Possono esserci casi misti: [abcq-z] trova a, b, c, q, r, s, t, u, v, w, x, y, z, esattamente come [a-cq-z].
Il carattere '-' è letterale solo se è primo o ultimo carattere nelle parentesi: [abc-] o [-abc]. Per trovare un carattere '[' o ']', il modo più semplice è metterli primi all'interno delle parentesi: [][ab] trova ']', '[', 'a' o 'b'. |
| [^ ] | Trova ogni singolo carattere non incluso nelle parentesi. Ad esempio, [^abc] trova ogni carattere diverso da "a", "b", o "c". [^a-z] trova ogni singolo carattere che non sia una lettera minuscola. Come sopra, questi due metodi possono essere usati insieme. |
| ^ | Corrisponde all'inizio della stringa (o di ogni riga della stringa, quando usato in modalità multilinea) |
| $ | Corrisponde alla fine della stringa o alla posizione immediatamente precedente un carattere di nuova linea (o alla fine di ogni riga della stringa, quando usato in modalità multilinea) |
| ( ) | Definisce una "sottoespressione marcata". Ciò che è incluso nell'espressione, può essere richiamato in seguito. Vedi sotto, \n. |
| \n | Dove n è una cifra da 1 a 9; trova ciò che la nesima sottoespressione ha trovato. Tale costrutto, detto backreference, estende le potenzialità delle regexp oltre i linguaggi regolari e non è stato adottato nella sintassi estesa delle regexp. |
| * |
|
| {x,y} | Trova l'ultimo "blocco" almeno x volte e non più di y volte. Ad esempio, "a{3,5}" trova "aaa", "aaaa" o "aaaaa". |
Vecchie versioni di grep non supportano il separatore alternativo "|".
Esempi:
- ".atto" trova ogni stringa di cinque caratteri come gatto, matto o patto
- "[gm]atto" trova gatto e matto
- "[^p]atto" trova tutte le combinazioni dell'espressione ".atto" tranne patto
- "^[gm]atto" trova gatto e matto ma solo all'inizio di una riga
- "[gm]atto$" trova gatto e matto ma solo alla fine di una riga
Dal momento che molte serie di caratteri variano a seconda della configurazione locale (in alcuni casi le lettere sono organizzate in abc..xyzABC...XYZ, in altri aAbB..yYzZ), lo standard POSIX ha definito alcune classi o categorie di caratteri come mostrato nella seguente tabella:
| classe POSIX | sintassi normale | significato |
|---|---|---|
| [:upper:] | [A-Z] | lettere maiuscole |
| [:lower:] | [a-z] | lettere minuscole |
| [:alpha:] | [A-Za-z] | lettera sia maiuscole che minuscole |
| [:alnum:] | [A-Za-z0-9] | numeri e lettere maiuscole e minuscole |
| [:digit:] | [0-9] | numeri |
| [:xdigit:] | [0-9A-Fa-f] | numeri in formato esadecimale |
| [:punct:] | [.,!?:...] | segni di interpunzione |
| [:blank:] | [ \t] | spazio o TAB |
| [:space:] | [ \t\n\r\f\v] | caratteri vuoti |
| [:cntrl:] | caratteri control | |
| [:graph:] | [^ \t\n\r\f\v] | caratteri non vuoti |
| [:print:] | [^\t\n\r\f\v] | caratteri non vuoti e spazi |
Le parentesi quadrate fanno parte della sintassi per indicare la classe di caratteri. Ad esempio [[:upper:][:digit:]ab] trova corrispondenza in una qualsiasi lettera maiuscola, in una qualsiasi cifra, nella lettera 'a' minuscola e nella lettera 'b' minuscola.
[modifica] Esempi di quantificatori
*Cerca l'occorrenza (zero o più volte) del carattere o insieme di caratteri cui segue:
abc*identificaabseguito da zero o piùc- come in
ab,abc,abcc,abccc
+Cerca l'occorrenza (una o più volte) del carattere o insieme di caratteri cui segue:
ab[ce]+identificaabseguito da una o piùcoppure una o piùe- come in
abc,abec,abccc,abcceeecccccce
?Cerca l'occorrenza (zero o una volta) del carattere o insieme di caratteri cui segue:
abc?identificaabseguito o meno da unac- come in
abceab
{m, n}Cerca l'occorrenza (da m a n volte; m lasciato vuoto è zero, n lasciato vuoto infinito) del carattere, insieme di caratteri o sotto-regex cui segue:
(ab){1,2}identifica le sequenze di uno o dueab- come in
abeabab
[modifica] Note
- ^ In realtà la regola dovrebbe essere rifinita, in modo da supportare anche i simboli non alfanumerici che compaiono prima e dopo la chiocciola, ma in questo esempio semplice li trascuriamo.
[modifica] Bibliografia
- Regular expression in Encyclopedia of Computer Science (in inglese), Hoboken, Wiley, 2003.
[modifica] Voci correlate
[modifica] Altri progetti
Wikibooks contiene un manuale sulle Espressione regolare
[modifica] Collegamenti esterni
|
|
o
(
(stringa vuota, ovvero la
(carattere,
)
indica l'insieme 
indica l'
indica l'

