Vai al contenuto

Regex: Espressioni regolari in PHP, parte 1

Qual è lo scopo di una macchina? Beh, teoricamente prendere “qualcosa” in ingresso, eseguire qualche tipo di lavoro e restituire il lavoro eseguito. L’esempio più semplice è il computer che prende in input dei dati, li elabora e restituisce un output come risultato. Tuttavia è una macchina anche un telefono: converte l’energia sonora in un segnale elettrico e lo ritrasforma in audio per rendere possibile la conversazione tra due punti. Un motore consuma carburante (vapore, fissione, benzina o olio di gomito) e lo trasforma in lavoro, energia, calore. E un frullatore mescola rum, ghiaccio, lime e curacao per produrre un buon cocktail estivo (se preferite qualcosa di più metropolitano, provate prosecco e succo di pesca e voilà un ottimo Bellini). In effetti, il frullatore è una macchina molto flessibile…

Poiché il software trasforma i dati in ingresso, ogni applicazione potrebbe essere considerata una macchina – “virtuale” ovviamente, data l’assenza di parti fisiche. Un compilatore, ad esempio, prende in input il codice sorgente e lo trasforma in codice binario per poter essere eseguito. Ma anche un semplice editor di immagini prende in input e produce pixel, applicando delle operazioni per ogni pixel o gruppi di pixel: i cosiddetti filtri ed effetti.

Quindi nonostante la sua caratteristica virtuale, il software si comporta come qualsiasi altra macchina: necessita dell’inserimento di materie prime, come ad esempio un elenco di numeri, dei dati incapsulati in XML o un comando di un protocollo. Ma se un programma viene “alimentato” con il materiale sbagliato – un tipo o una forma diversa da quello richiesto – il risultato rischia di essere imprevedibile se non catastrofico. Provate a mettere dei sassolini all’interno di un frullatore e mi fate sapere… Un famoso detto in campo informatico dice: “Garbage in, garbage out“.

Tutti i problemi non banali richiedono un controllo sui dati di input, un “filtro” che impedisca l’inserimento di dati errati e prevenire così un output di conseguenza errato. Questo è certamente il caso delle applicazioni web sviluppate in PHP. Se l’input proviene da un form o da una richiesta Ajax, il programma dovrebbe controllare i dati di input prima di eseguire qualsiasi tipo di calcolo. Potrebbe darsi il caso che un valore numerico debba essere scelto nei limiti di un range di numeri, oppure che debba essere un numero positivo o di una certa lunghezza. Potrebbe verificarsi il caso di dover inserire un formato specifico, come un codice di avviamento postale. In italia i CAP sono di 5 cifre, oppure una partita IVA, a 11 cifre. Oppure ancora una data di nascita nel formato italiano gg/mm/aaaa. Insomma, un’applicazione PHP deve essere sviluppata in modo robusto tenendo conto di questi fattori e di tutti i potenziali pericoli esterni che potrebbero alterare il comportamento dell’applicazione o eludere la sicurezza.

Ma come fa un programma a capire se un dato in input è conforme, ad esempio, a un codice postale? Fondamentalmente, è necessario implementare un piccolo parser per effettuare il match dei dati: a tutti gli effetti un automa a stati finiti in grado di leggere l’input, processare i dati, monitorare lo stato e restituire un risultato. Ma creare un semplice parser potrebbe in realtà essere molto complicato.

400px-NFAexample.svg

Per fortuna, le operazioni di “pattern-matching” in informatica sono molto comuni (fin dagli albori di UNIX o giù di lì) e ciò ha consentito lo sviluppo di librerie e funzioni che col tempo si sono evoluti. Un’espressione regolare (regex) descrive un modello (che d’ora in poi chiameremo pattern) che, grazie a una particolare notazione concisa e leggibile, consente di raggruppare, descrivere, identificare stringhe che presentino una certa regolarità al suo interno.

regex-example

Un esempio di espressioni regolari lo fornisce il comando grep di Unix (o Linux), che cerca un pattern specifico dentro uno o più file di testo in Unix. Il comando

grep -i -e '^Bat'

ricerca nei contenuti dei file le corrispondenze che hanno un inizio di linea (indicata con l’accento circonflesso ^), seguita immediatamente dalle lettere b, a, e t (l’opzione -i serve per ad ignora il case sensitive, quindi B e b sono equivalenti). Quindi, dato il file eroi.txt:

Catwoman
Batman
The Tick
Black Cat
Batgirl
Danger Girl
Wonder Woman
Luke Cage
The Punisher
Ant Man
Dead Girl
Aquaman
SCUD
Blackbolt
Martian Manhunter

Il comando grep produrrebbe due corrispondenze:

Batman
Batgirl

Molti fanno la prima conoscenza delle espressioni regolari grazie ai file .htaccess in ambiente Linux, ad esempio, per il rewrite url ma questa è solo una minima parte. In qualsiasi altro linguaggio di programmazione, le espressioni regolari sono ampiamente utilizzate. In particolare nel PHP abbiamo due metodi per la definizione di espressioni regolari, uno chiamato Portable Operating System (POSIX) e un altro Perl Compatible Regular Expressions (PCRE). In generale è preferibile utilizzare PCRE, perché è molto più potente di POSIX, in quanto offre tutti gli operatori presenti in Perl, che è il re indiscusso delle espressioni regolari. Nel prossimo articolo vedremo le caratteristiche base dello standard PCRE.