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