Le espressioni regolari. - Home Page di Andrea Leotardi

Transcript

Le espressioni regolari. - Home Page di Andrea Leotardi
Lezione 8 Le espressioni regolari.
Corrispondenze e classi di caratteri.
Le espressioni regolari.
Le regular expressions (espressioni regolari) servono per descrivere dei modelli di stringa. E’
possibile verificare, ad esempio, se un codice fiscale o un indirizzo email sono stati inseriti
correttamente.
Infatti, le funzioni viste la volta scorsa non sono molto flessibile e potenti come lo strumento
che vedremo in questa lezione. E’ bene dire però, che l’uso delle espressioni regolari porta un
sensibile overhead di esecuzione; quindi, dove è possibile usare le funzioni dedicate alle
stringhe è inutile utilizzare le espressioni regolari, che portano un aumento del tempo di
esecuzione.
PHP supporta sia le espressioni regolari che seguono lo standard POSIX sia quelle stile Perl
(Perl regular expressions).
Noi ci occuperemo del primo gruppo. Daremo comunque un cenno anche alle espressioni
regolari Perl, più complicate da apprendere ma anche più potenti.
Corrispondenze e classi di caratteri.
Con la funzione ereg() si possono intercettare le corrispondenze di modelli nelle stringhe. La
sintassi della funzione è la seguente :
Sintassi:
$res = ereg(“modello”,$stringa,$array);
La funzione ereg() restituisce il numero di caratteri trovati nelle corrispondenze e memorizza in
$array le corrispondenze trovate nella variabile $stringa, in base al modello usato.
La difficoltà nell’uso delle espressioni regolari sta proprio nel capire la “sintassi” dei modelli.
Essi possono essere semplici caratteri, contenere quantificatori, classi di caratteri.
Ad esempio :
$num=ereg(“gio”,”ciao Gigio”,$array);
print $num.’---‘.$array[0];
L’output sarà 3---gio .
Per apprezzare però le qualità delle regular expressions si osservi attentamente la seguente
tabella :
Simbolo Funzione
.
Qualsiasi carattere
successivo.
?
Nessuna o una istanza del
carattere.
*
Nessuna o più istanze del
carattere.
+
Una o più istanze.
{n}
Esattamente n istanze
successive del carattere.
{n,}
n o più istanze.
{,n}
Al massimo n istanze.
{n,m} Trova le corrispondenze
con almeno n istanze ma
Esempio
g.
g?
g*
g+
g{2}
g{2,}
g{,3}
g{2,3}
Domenico Nappo – Domenico Surace - Manuali.Net © Tutti i diritti riservati
Corrispondenze e classi di caratteri.
al massimo m istanze.
Prima di far vedere qualche esempio utile, bisogna parlare delle classi di caratteri.
Le classi permettono di trovare le corrispondenze di un carattere appartenente ad una
determinata classe, come un numero, un carattere alfabetico e così via.
Nella tabella sono riportati esempi di classi :
Classe
[a-z]
[A-Z]
Descrizione
Trova tutti i caratteri
minuscoli.
Trova i caratteri maiuscoli.
[0-9]
Trova un numero.
[^0-9]
Trova tutto ciò che è diverso
da un numero.
Esempio
[a-z]{4} : Trova un gruppo di
4 caratteri minuscoli.
[A-Z]+ : Trova una o più
istanze di un carattere
maiuscolo.
[0-9]{5} : Trova un gruppo di
5 numeri (ad esempio un
CAP).
[^0-9]* : Trova tutto ciò che
non è un numero.
Parliamo ora di atomi. Racchiudendo fra parentesi un modello e sfruttando i simboli
quantificatori visti nella prima tabella, è possibile formulare complesse espressioni regolari. A
titolo di esempio, riportiamo vari blocchi di codice per controllare, ad esempio, dei dati ricevuti
dall’utente tramite un form HTML (parleremo più avanti nel corso come inviare dati ad uno
script PHP tramite i form) :
if ((empty($nominativo))||(ereg("[^a-zA-Z\ ]+",$nominativo,$array)))
{
print $nominativo.’ Non è un dato corretto’;
}
Come vedete, se la variabile $nominativo è vuota o all’interno sono stati trovate una o più
corrispondenze di caratteri non alfabetici (compreso lo spazio), viene segnalato un messaggio
di errore.
if ((empty($email))||(!ereg("([a-zA-Z0-9\.]+)(@{1})([a-zA-Z0-9]{2,})\.([a-zA-Z09]{2,})",$email,$array))||(ereg("([\|\<\>\\\/]+)",$email,$array)))
{
print $email.’ Non è un indirizzo corretto’;
}
Non spaventatevi!;) L’istruzione if precedente dovrebbe essere scritta su una sola riga.
Analizziamo con calma l’espressione booleana. Se $email è vuota oppure è diversa dal modello
descritto in ereg(), viene segnalato errore.
Il modello può essere spiegato semplicemente nel seguente modo :
il primo atomo verifica una o più occorrenze di caratteri alfanumerici, compreso il punto (si noti
il carattere di escape \ davanti al punto, per evitare che ci sia ambiguità con il carattere di
controllo visto prima).
Il secondo atomo si accerta della presenza di un’unica occorrenza del carattere @.
Il terzo atomo e quarto atomo verificano la presenza di almeno 2 occorrenze di caratteri
alfanumerici, seguiti da un punto,e seguiti ancora da almeno 2 caratteri alfanumerici.
Domenico Nappo – Domenico Surace - Manuali.Net © Tutti i diritti riservati
Lezione 8 Le espressioni regolari.
Manipolazione di stringhe tramite le RE.
La seconda chiamata ad ereg() serve per controllare che non siano presenti caratteri strani del
tipo <,>,\,|,/ (tutti preceduti da caratteri di escape), per evitare ‘manovre’ strane da utenti
maliziosi.
Questa purtroppo non è la sede adatta per parlare di problemi di sicurezza, ma vi consiglio
caldamente di approfondire l’argomento se volete intraprendere la carriera del programmatore
web professionista.
Non avete idea di quanti portali (del valore anche di centinaia di milioni) sono vulnerabili non
per via del software utilizzato, come un particolare server web, ma per colpa di una cattiva
programmazione o gestione del sito (su molti siti è possibile visualizzare user e password di
connessione al database in chiaro, e la cosa grave è che alcuni utilizzano le stesse password
sia per accedere alle cartelle del sito via ftp che per connettersi al database!!!).
Adesso un altro esempio utile :
if ((empty($codice))||(!ereg("([a-zA-Z]){6}([0-9]){2}([a-zA-Z]){1}([0-9]){2}([azA-Z]){1}([0-9]){3}([a-zA-Z]){1}",$codice,$array)))
{
print $codice.’ Non è un codice fiscale corretto’;
}
Conoscendo la struttura di un codice fiscale, è possibile scrivere un semplice modello per
un’espressione regolare che verifichi la correttezza di questo dato.
Infatti, un corretto codice fiscale può essere MDNTMS68C23E101W. Come potete osservare,
l’espressione regolare rispecchia fedelmente la struttura, cioè prima sei caratteri alfabetici, poi
due cifre decimali etc. etc.
Manipolazione di stringhe tramite le RE.
Una funzione molto utile è la ereg_replace(), per sostituire modelli nelle stringhe.
L’unica differenza con ereg(), è il fatto che ereg_replace(), oltre a trovare le corrispondenze,
effettua anche una sostituzione, ritornando la stringa manipolata :
Sintassi:
$stringa_res=ereg_replace(modello,replacement,$stringa);
Tralasciando il semplice esempio di sostituzione di stringa (effettuabile più efficacemente con la
funzione str_replace() vista nella scorsa lezione), introduciamo anche l’uso dei riferimenti
all’indietro con ereg_replace().
Si racchiudono tra parentesi i singoli elementi di espressione regolare. Nel replacement,
ognuno di essi sarà i dentificato da un numero intero di sequenza. Ad ogni atomo di
espressione regolare, è possibile applicare una diversa sostituzione.
Presentiamo un esempio classico: convertiamo una data in formato mm/gg/aaaa in
gg/mm/aaaa :
$date=02/28/2002;
$data=ereg_replace(“([0-9]+)/([0-9]+)/ ([0-9]+)”,\\2/\\1/\\3,$date);
$data conterrà la stringa 28/02/2002.
Domenico Nappo – Domenico Surace - Manuali.Net © Tutti i diritti riservati
Un cenno alle espressioni regolari Perl .
Un cenno alle espressioni regolari Perl .
Le espressioni regolari Perl possono tornare utili in alcuni casi. Parleremo brevemente delle
PCRE dando giusto qualche esempio e qualche spunto da cui poter studiare in seguito.
Una PCRE viene racchiusa dai delimitatori ‘/’.
La funzione simile alla ereg() vista prima è la preg_match() :
$testo=’Antongianni’;
if ((preg_match(“/i.n/”,$testo,$array) )
{
print $array[0]; //stampa ian
}
Se utilizziamo invece la /i.*n/ viene stampato iann (* significa ‘quanti più caratteri è possibile
prima della n).
Usando /i.?n/ (? = quanti meno caratteri è possibile prima di una n), viene stampato di nuovo
ian.
Tramite preg_match_all() è possibile memorizzare in $array tutte le occorrenze trovate
(mentre con le POSIX RE ciò non è possibile in maniera immediata).
Tramite la funzione preg_replace(), è possibile impostare dei parametri per permettere la
sostituzione non di tutte le occorrenze (come avviene per la ereg_replace()) , ma un numero
prefissato di occorrenze.
Immaginiamo di voler analizzare l’url da cui proviene un utente, prelevando soltanto il dominio
principale (cioè da http://www.dominio.com/sottocartella/votami.php vogliamo soltanto
analizzare http://www.dominio.com ).
Infatti, in un sistema di votazione, vogliamo controllare che il voto provenga da un
determinato dominio inserito in un database. Ma se nel database l’utente ha inserito un
indirizzo del tipo http://www.dominio.com/sottocartella/votami.php, ma vuole permettere
anche la votazione dalle altre pagine del sito, bisogna verificare soltanto la presenza del
dominio principale e non dell’url esatto da cui proviene il voto.
$siteurl=’ http://www.dominio.com/sottocartella/votami.php’;
if ($test=substr($siteurl,-1)<>'/')
$siteurl.='/'; //aggiunge / serve per la preg_match
preg_match("/h.*?\/\/.*?\//",$siteurl,$array);
$dominio=$array[0]; //inserisce soltanto il dominio base
if (strstr($HTTP_REFERER,$dominio))
print ‘ok, voto valido perchè proveniente dal dominio registrato’;
La preg_match() preleva tutto ciò che inizia con h fino alla terza occorrenza di una barra
inversa
(/).
Quindi,
nel
nostro
esempio,
$dominio
conterrà
la
stri nga
http://www.dominio.com/.
$HTTP_REFERER è una variabile globale che contiene l’indirizzo di provenienza (ad esempio
http://www.dominio.com/altracartella/votamiancora.php ). Tramite la funzione strstr() viene
verificata la presenza della sottostringa $dominio all’interno dell’url di provenienza.
Domenico Nappo – Domenico Surace - Manuali.Net © Tutti i diritti riservati
Lezione 8 Le espressioni regolari.
Un cenno alle espressioni regolari Perl .
Anche per questa volta è tutto. Nella prossima lezione parleremo delle funzioni PHP dedicate ai
files. Non mancate!!
2002 By Domenico Nappo aka WebdoM.
L’autore declina ogni responsabilità per eventuali (quanto improbabili) danni recati al sistema
per l’uso degli script di esempio riportati in questa guida.
Domenico Nappo – Domenico Surace - Manuali.Net © Tutti i diritti riservati