Espressione regolare

Da Wikipedia, l'enciclopedia libera.
(Reindirizzamento da Espressioni regolari)
Se hai problemi nella visualizzazione dei caratteri, clicca qui.

Una espressione regolare (in lingua 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, pertanto 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 riconosciuti da automi a stati finiti.

Indice

Definizione [modifica]

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.

Storia [modifica]

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.

Dal 2000 in poi le espressioni regolari sono disponibili nella maggioranza degli editor di testo per GNU/Linux e altri sistemi unix-like.[senza fonte]

Espressioni regolari nei linguaggi formali [modifica]

Le espressioni regolari sono composte da costanti e operatori che denotano insiemi di stringhe, e da operazioni tra questi insiemi.

Dato un alfabeto finito \Sigma, sono definite le seguenti costanti:

  1. \varnothing o \emptyset (insieme vuoto)
  2. \epsilon (stringa vuota, ovvero la stringa di lunghezza 0)
  3. \left \{ a \right \} (carattere, \forall a \in \Sigma)

e le seguenti operazioni:

  1. concatenazione: RS o R \circ S indica l'insieme \left \{ \alpha \beta / \alpha \in R \and \beta \in S \right \}
  2. unione: R \cup S indica l'unione dei due insiemi
  3. stella di Kleene: R^{*} indica l'insieme che contiene tutte le possibili iterazioni ottenibili dagli elementi di R
  4. intersezione: R \cap S indica l'intersezione tra i due insiemi di stringhe
  5. complemento: il complementare di R indica l'insieme delle stringhe appartenenti a \Sigma^{*} \setminus R

Ad esempio dati R = \left \{ a, b \right \} e S = \left \{ 7, 8 \right \}, RS = \left \{ a7, b7, a8, b8 \right \} e S^{*} = \left \{ \epsilon, 7, 8, 77, 78, 87, 88, 777, 778, \cdots \right \}

Allora, possiamo dire che un'espressione regolare, definita a partire da un alfabeto \Sigma ed un insieme di simboli \left \{ +, *, (, ), ., \emptyset \right \}, è una stringa R \in {\left ( \Sigma \cup \left \{ +, *, (, ), ., \emptyset \right \} \right )}^{+} che rende vera alcuna delle seguenti condizioni:

  1. R = \emptyset
  2. R \in \Sigma
  3. R = S + T o R = ST o R = S^{*}, dove S e T sono espressioni regolari sull'alfabeto \Sigma

Impiego delle espressioni regolari [modifica]

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.

Sintassi [modifica]

Espressioni regolari tradizionali di UNIX [modifica]

La sintassi di base delle espressioni regolari in UNIX è attualmente definita obsoleta[non chiaro] 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. Ad esempio: "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". Il risultato di 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.
*
  • Un'espressione costituita da un singolo carattere seguito da "*", trova zero o più copie di tale espressione. Ad esempio, "[xyz]*" trova "", "x", "y", "zx", "zyx", e così via.
  • \n*, dove n è una cifra da 1 a 9, trova zero o più iterazioni di ciò che la nesima sottoespressione ha trovato. Ad esempio, "(a.)c\1*" trova "abcab" e "accac" ma non "abcac".
  • Un'espressione racchiusa tra "\(" e "\)" seguita da "*" non è valida. In alcuni casi (es. /usr/bin/xpg4/grep di SunOS 5.8), trova zero o più ripetizioni della stringa che l'espressione racchiusa ha trovato. In altri casi (es. /usr/bin/grep di SunOS 5.8), trova ciò che l'espressione racchiusa ha trovato, seguita da un letterale "*".
{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.

Esempi di quantificatori [modifica]

  • * Cerca l'occorrenza (zero o più volte) del carattere o insieme di caratteri cui segue:
abc* identifica ab seguito 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]+ identifica ab seguito da una o più c oppure 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? identifica ab seguito o meno da una c
come in abc e ab
  • {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 due ab
come in ab e abab

Note [modifica]

  1. ^ 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.

Bibliografia [modifica]

  • Regular expression in Encyclopedia of Computer Science (in inglese), Hoboken, Wiley, 2003.

Voci correlate [modifica]

Altri progetti [modifica]

Collegamenti esterni [modifica]

Informatica Portale Informatica: accedi alle voci di Wikipedia che trattano di Informatica