PHP/Programmazione/Regexp
Wikibooks, manuali e libri di testo liberi.
- Introduzione PHP/Introduzione
- Installazione e configurazione PHP/Installazione e configurazione
- Programmazione PHP/Programmazione
- Una pagina PHP PHP/Programmazione/Una pagina PHP
- echo PHP/Programmazione/echo
- Commenti PHP/Programmazione/Commenti
- Variabili PHP/Programmazione/Variabili
- Operatori PHP/Programmazione/Operatori
- Array PHP/Programmazione/Array
- Condizioni PHP/Programmazione/Condizioni
- Cicli PHP/Programmazione/Cicli
- Funzioni di base PHP/Programmazione/Funzioni di base
- Funzioni personalizzate PHP/Programmazione/Funzioni personalizzate
- Variabili globali PHP/Programmazione/Variabili globali
- $GLOBALS PHP/Programmazione/Variabili globali/$GLOBALS
- $_GET PHP/Programmazione/Variabili globali/$_GET
- $_POST PHP/Programmazione/Variabili globali/$_POST
- $_SESSION PHP/Programmazione/Variabili globali/$_SESSION
- $_COOKIE PHP/Programmazione/Variabili globali/$_COOKIE
- $_SERVER PHP/Programmazione/Variabili globali/$_SERVER
- File PHP/Programmazione/File
- Immagini PHP/Programmazione/Immagini
- Espressioni regolari PHP/Programmazione/Regexp
- Programmazione orientata agli oggetti PHP/Programmazione/OOP
- Programmazione avanzata con le classi PEAR PHP/PEAR
- PHP e i database PHP/Database
- Funzioni PHP per l'accesso ai database
- Database e object oriented PHP/Dboop
- PHP Design Pattern PHP/PHP Design Pattern
- Smarty PHP/Smarty
- Sicurezza delle applicazioni web PHP/Sicurezza
- PHP CLI: Command Line Interpreter PHP/Cli
- PHP GTK2: applicazioni desktop in PHP PHP/Gtk
- Wikibook credits
Le espressioni regolari sono uno strumento molto potente, che consente complesse elaborazioni testuali.
In questa sede ci limiteremo ad illustrare il funzionamento delle regex su PHP senza però spiegare effettivamente come si scrivono le regular expressions (cosa infatti non semplice e di certo impossibile da fare in una pagina).
Per le espressioni regolari sono stati scritti varie funzioni, quelle più famose sono la coppia _ereg e il package PCRE (acronimo di "Perl Compatible Regular Expressions" ovvero Regex compatibili con Perl). Le prime tuttavia non hanno le stesse funzionalità avanzate del package PCRE, pertanto analizzeremo queste ultime in particolare (se però si vuole avere una visione anche sulle prima, basta visitare questo link).
Indice |
[modifica] PCRE
Questa libreria è un porting in PHP di un'altra molto utilizzata e diffusa, scritta per Perl. Essa viene anche chiamata colloquialmente preg_match.
[modifica] Ottenere dei dati
Vediamo un esempio di come si utilizza una regex in PHP:
<?php $regex = "/\[\[[Ii]m(?:age|magine):(.*?)\]\]/"; $testo = "[[Immagine:Ciao.jpg]], [[image:hello.jpg]], image:hello.jpg"; preg_match($regex, $testo, $risultato); print_r($risultato) ?>
Se proviamo ad eseguire questo script, otterremo come risultato:
Array
(
[0] => [[Immagine:Ciao.jpg]]
[1] => Ciao.jpg
)
La regex utilizzata serve per trovare tutte le immagini in markup wiki; in particolare restituisce il suo nome reale (ovvero, senza il namespace immagine).
In PHP una regex deve essere definita in una stringa di testo che inizia e finisce con "/" per far capire al motore che quella è una regex e non testo qualunque. La funzione preg_match prende il primo parametro (la regex), lo confronta col secondo (il testo) e assegna il risultato alla variabile indicata come terzo parameetro (nel nostro caso $risultato , che noi mostriamo con la funzione print_r).
La variabile di risultato conterrà il testo associato dall'intera regex e l'evenutale testo dei cosidetti backreference indicati tra le parentesi (nel nostro caso rispettivamente $risultato[0] e $risultato[1]). La prima parentesi non viene restituita come backreference solo perché è stato utilizzato il modificatore ?: che indica al motore delle regex di non contare quelle determinate parentesi per le backreference (ciò serve per rendere la regex più veloce).
Perché, però, non prende anche image:hello? Perché preg_match restituisce solo la prima occorrenza, per ottenerle tutte bisogna usare preg_match_all:
<?php $regex = "/\[\[[Ii]m(?:age|magine):(.*?)\]\]/"; $testo = "[[Immagine:Ciao.jpg]], [[image:hello.jpg]], image:hello.jpg"; preg_match_all($regex, $testo, $risultato); print_r($risultato); ?>
Risultato:
Array
(
[0] => Array
(
[0] => [[Immagine:Ciao.jpg]]
[1] => [[image:hello.jpg]]
)
[1] => Array
(
[0] => Ciao.jpg
[1] => hello.jpg
)
)
In questo modo abbiamo quindi sia "il pezzo di codice" che volevamo passare al parser che il risultato nello specifico.
Abbiamo quindi due array annidati dentro un altro, pertanto per accedere al primo basterà usare $risultato[0], mentre $risultato[1] per il secondo. Per accedere invece, per esempio, a Ciao.jpg, basterebbe utilizzare $risultato[1][0].
[modifica] Sostituire dei dati con degli altri (replace)
Poniamo per esempio di dover cambiare tutti le stringhe di wikicodice [[Image:x]] con [[Immagine:x]] per ovviare a degli ipotetici problemi tecnici del motore wiki.
<?php $testo = "[[image:ciao.png]], [[Image:CIAO.jpeg]]"; $regex = "/\[\[[Ii]mage:(.*?)\]\]/"; $regex2 = "[[Immagine:\\1]]"; $risultato = preg_replace($regex, $regex2, $testo); print $risultato; ?>
Il risultato di questo script è:
[[Immagine:ciao.png]], [[Immagine:CIAO.jpeg]]
In questo modo abbiamo definito una prima regex per ottenere le sottostringhe e poi una seconda per indicare con cosa sostituire il testo associato dalla prima. Dato che la seconda è una stringa e la backslash (\) è un carattere speciale in PHP, bisogna farne l'escape(aggiungendo quindi un'altra backslash) per ottenere un backreference (riferimento all'indietro, ovvero andare a prendere la parentesi identificata dal numero).
Attenzione:
preg_replacerestituisce un valore tramite assegnamento (ovvero, dovete usare la sintassi$variabile = preg_replace();) al contrario di quanto facevapreg_match[_all])- Questa regex non è la migliore in quanto il tutto potrebbe essere fatto semplicemente sostituendo "/\[\[[Ii]mage:/" con "[[Immagine". La parte superflua è stata tuttavia inserita ad esclusiva finalità didattica (per spiegare come usare le backreference correttamente).
[modifica] Modificatori
| Modificatore | Descrizione |
|---|---|
| i | Rende le regex case-insensitive. |
| m | Permette la modalità multi-riga, così ^ si ancora all'inizio di ogni frase e $ alla fine sempre di ogni frase. |
| s | Permette la modalità mono-riga, così ^ si ancora all'inizio del testo e $ alla fine (di tutto il testo). Il metacarattere "." può essere utilizzato per "prendere" anche gli a-capo. |
| x | Modalità estesa, gli spazi dentro la regex fuori da espressioni vengono ignorati, permette inoltre di commentare le regex con #. |
| e | La stringa (la $regex2 usata sopra) usata in preg_replace viene elaborata come codice PHP. |
| A | Àncora la regex per forza all'inizio del testo. |
| D | Il carattere $ ancora solo a fine testo. |
| u | Modalità unicode. |
I modificatori servono a modificare il comportamento del motore di regex utilizzato. Per esempio, la regex usata sopra per "italianizzare" tutte le immagini, diventerebbe:
<?php $testo = "[[image:ciao.png]], [[Image:CIAO.jpeg]]"; $regex = "/\[\[image:(.*?)\]\]/i"; $regex2 = "[[Immagine:\\1]]"; $risultato = preg_replace($regex, $regex2, $testo); print $risultato; ?>
Con risultato: [[Immagine:ciao.png]], [[Immagine:CIAO.jpeg]]
Come si può vedere, il risultato è identico sebbene l'espressione regolare non sia la stessa (notare in particolare la i dopo l'ultimo slash - / - della regex).
[modifica] Particolarità
Le backreference (quelle di solito identificate come \1 o \\1 in php) possono anche essere richiamate con $1 (sostituendo l'1 al numero desiderato) come si fa in Perl.
[modifica] Bibliografia
[modifica] Collegamenti esterni
- (EN) www.regular-expressions.info esempi, tutorial e guide sulle regex.
- Guida in italiano a regex di base.