Generalità

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”.

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.

In ambiente Unix/Linux esiste il comando chiamato global regular expression print, grep.

Le espressioni regolari sono utilizzate principalmente da editor di testo per la ricerca e la sostituzione di porzioni del testo.

La sintassi delle espressioni regolari in UNIX in base allo standard POSIX, esiste in due versioni diverse:

  • la sintassi detta di base, è quella che è stata creata per prima ed è la più diffusa, un esempio di applicativo che la usa è ed;

  • la sintassi detta nuova, cioè quella che è stata definita con lo standard POSIX.2, viene usata ad esempio da egrep.

[In informatica, POSIX (o Posix: Portable Operating System Interface for Unix) è il nome che indica la famiglia degli standard definiti dall’IEEE denominati formalmente IEEE 1003. Il nome standard internazionale è ISO/IEC 9945.Gli standard POSIX derivano da un progetto, iniziato intorno al 1985, finalizzato alla standardizzazione delle API per i software sviluppati per le diverse varianti dei sistemi operativi UNIX. ]

Pattern (modello)

Un’espressione regolare può essere suddivisa in:

  • caratteri ordinari: trovano una corrispondenza diretta nelle stringe dell’insieme denotato
  • metacaratteri: caratteri speciali che assumono caratteristiche di controllo sui caratteri ordinari

Lista dei metacaratteri:

[ ] \ { } | ( ) ^ ? + * .
Metacarattere Descrizione
. indica qualsiasi carattere (escluso un accapo)
* indica zero o più occorrenze (di un carattere o di un gruppo di caratteri)
? indica zero o una occorrenza (di un carattere o di un gruppo di caratteri)
{} le parentesi graffe, che indicano il numero esatto, o minimo, o massimo, o l’intervallo di occorrenze (di un carattere o di un gruppo di caratteri)
+ indica una o più occorrenze (di un carattere o di un gruppo di caratteri)
^ indica l’inizio della stringa (o, se all’interno di una classe di caratteri, la negazione della stessa)
$ indica la fine della stringa
| indica l’operatore OR
\ il carattere di escape dei caratteri speciali
() le parentesi tonde, destinate a contenere una sottostringa
[] le parentesi quadre, destinate a contenere una ‘classe’ di caratteri

Elementi di base:

  • Atomo: un carattere ordinario, un gruppo di caratteri (delimitato da []) o un ’ espressione regolare fra parentesi tonde Sono atomi: a,[abc],(abc),(a*b+c?) … Una qualunque espressione racchiusa da () diventa un atomo
  • Parte: un atomo eventualmente seguito da un quantificatore Sono parti: a,a*,a{5,6},(a*b+),(a*b+)?

Espressione banale: è la forma più semplice (e più banale) di espressione regolare costituita solo dacaratteri ordinari (senza metacaratteri). Identifica un insieme composto da un solo elemento: lastringa uguale all’espressione stessa Esempio: l’espressione banana identifica solo la stringa “banana

Esempi di espressioni con quantificatori:

  • a*b+c?: 0 o più occorrenze di a, seguite da 1 o più b seguite da 0 o 1 occorrenza di c., stringhe ammissibili: a,ab,abc,bb,abb,abbc,aa
  • Ar(har){1,2}ha : ”Ar” seguito da 1 o due occorrenze di ”har” seguita da ”ha”, stringhe ammissibili: Arharha,Arharharha
  • Ar*gh : ”A” seguita da un numero qualunque di ”r” seguita da ”gh”,stringhe ammissibili: Argh,Arrgh,Arrrrgh

Il quantificatore si applica all’ atomo che lo precede se scriviamo ab+ il quantificatore agisce solo su ‘b’,se vogliamo applicarlo ad “ab” scriveremo (ab)+

Le parentesi quadre [] racchiudono una “classe di caratteri”. Questo vuol dire che il modello può o deve contenere alcuni o tutti i caratteri in esse contenute; chiariamo il concetto con degli esempi:

  • [abc] : questo modello è soddisfatto quando viene trovata una delle lettere, senza tener conto dell’ordine in cui sono presenti;

  • [a-z] : in questo modello è presente un intervallo di caratteri (notare il segno -, sta per “dalla a alla z”), esso è soddisfatto quando viene trovato uno qualsiasi dei caratteri compresi nell’intervallo;

  • [0-9] : in questo modello è presente invece un intervallo di numeri, esso è soddisfatto quando viene trovato uno qualsiasi dei numeri compresi nell’intervallo;

  • [a-z0-9\?] : questo modello è leggermente più complesso, ma dovrebbe essere di facile comprensione. La corrispondenza viene trovata quando la stringa contiene una lettera (minuscola in questo caso), un numero o il carattere ? (notate il segno \ prima di ?, perché il punto interrogativo è un carattere speciale, che qui però assumiamo per il suo valore letterale);

  • [^a-z] : questo modello è soddisfatto quando viene trovato un qualsiasi carattere che non sia una lettera minuscola (notate il segno ^ che all’interno della classe, la nega);

Naturalmente una classe di caratteri può essere seguita (e normalmente lo è) da uno dei metacaratteri che indicano il numero di volte in cui uno dei caratteri in essa contenuti, deve essere presente, riprendendo l’ultimo modello:

Un quantificatore (quantifier) vincola l’atomo che lo precede a comparire tante volte quanto indicato (m e n sono valori numerici generici)

  • {n}: esattamente n volte
  • {m,n}: almeno m e al più n volte
  • {0,n}: al più n volte
  • {m,}: almeno m volte

Quindi: {3,7} significa da 3 a 7 volte

Sono previste anche forme abbreviate (sono quelle usate anche dai DTD:

  • * equivale a {0,}
  • + equivale a {1,}
  • ? equivale a {0,1}
  • [a-z0-9\?]? : i caratteri contenuti nella classe devono essere presenti zero o una volta;
  • [a-z0-9\?]* : i caratteri contenuti nella classe devono essere presenti zero o più volte;
  • [a-z0-9\?]{3} : i caratteri contenuti nella classe devonoo essere presenti esattamente tre volte;
  • [a-z0-9\?]{1,3} : i caratteri contenuti nella classe devono essere presenti da una a tre volte;
  • [a-z0-9\?]{3,} : i caratteri contenuti nella classe devono essere presenti minimo tre volte;
  • [a-z0-9\?]{,3} : i caratteri contenuti nella classe devono essere presenti massimo tre volte.

Le parentesi tonde, invece, fanno riferimento ad una sottostringa, o una parte di stringa se preferite, che viene assunta per il suo esatto valore letterale. Quindi ad esempio (abc) si riferisce all’esatta sequenza di caratteri abc, a differenza, come abbiamo visto, di [abc] che si riferisce invece ad uno dei tre caratteri.

Il carattere | (pipe) indica l’operatore OR e consente, quindi, di presentare più alternative per un’espressione; ad esempio (bello|normale|brutto) va letta come “bello o normale o brutto” ed è quindi soddisfatta quando solo una delle tre parole viene trovata nella stringa analizzata.

Sul carattere ^ (accento circonflesso) vale la pena di soffermarsi un attimo perchè, come accennato, esso assume una duplice valenza, a seconda del punto in cui si trovi all’interno dell’Espressione Regolare ed occorre quindi porre molta attenzione nel suo uso.

  • Se posto all’inizio del modello, tale carattere indica l’inizio esatto dello stesso: ^(ciao) indica infatti che la stringa deve iniziare con la parola ciao.
  • Ma l’accento circonflesso, se posto all’interno di una classe di caratteri, nega la stessa: [^0-9] indica qualsiasi carattere che non sia un numero.

Infine, il carattere $ indica la fine di una stringa, per cui se viene usato in combinazione con ^, è possibile costruire un’Espressione Regolare che indichi un modello esattamente contenuto in una stringa, ad esempio ^Ciao come stai \?$, o che indichi l’esatto inizio e l’esatta fine di una stringa, ad esempio ^(Ciao) [a-zA-Z]+ (come stai \?)$

Le Espressioni Regolari hanno delle abbreviazioni:

  • \d equivale a [0-9]
  • \D equivale a [^0-9]
  • \w equivale a [0-9A-Za-z]
  • \W equivale a [^0-9A-Za-z]
  • \s equivale a [ \t\n\r]
  • \S equivale a [^ \t\n\r]

Esempi:

  • RSS MRA 80B21 H501V → [A-Z]{6}\d{2}[A-Z]\d{2}[A-Z]\d{3}[A-Z] (codice fiscale)
  • \d*[50] → Tutte le cifre che vogliamo basta che l’ultima cifra sia 0 o 5
  • \d*\.\d{2} → Tutte le cifre che vogliamo basta che ci sia il carattere “.” seguito da 2 cifre. Per inserire “.” abbiamo dovuto usareun carattere di escape .

Gruppi

(regex) : Parentheses group the regex between them. They capture the text matched by the regex inside them into a numbered group that can be reused with a numbered backreference. They allow you to apply regex operators to the entire grouped regex.

Esempio1:

regex : (https?|ftp):\/\/([^\r\n]+)([^\r\n]*)?

sulla stringa https://stackoverflow.com/

produce :

Match 1
Full match 0-26 https://stackoverflow.com/
Group 1. 0-5 https
Group 2. 8-26 stackoverflow.com/
Group 3. 26-26 ``