Espressioni Regolari in PHP
Scopri come usare le espressioni regolari in PHP con le funzioni preg_: validazione, estrazione e sostituzione di testo.
Un'espressione regolare (regex) è un pattern che descrive un insieme di stringhe. Invece di cercare un testo fisso, si descrive la sua forma — "un indirizzo email", "una sequenza di cifre", "una parola che termina in .php" — e PHP trova, valida, sostituisce o divide il testo che corrisponde.
Questo capitolo spiega come funzionano le funzioni preg_ di PHP, la sintassi di un pattern (delimitatori, classi di caratteri, quantificatori, gruppi, ancore) e le operazioni più comuni: validare l'input, estrarre dati e sostituire testo.
Cosa sono le espressioni regolari
Un'espressione regolare è una sequenza di caratteri che definisce un pattern di ricerca. La maggior parte dei caratteri corrisponde a se stessa — il pattern cat corrisponde al testo letterale cat. La potenza deriva dai metacaratteri che rappresentano categorie di caratteri o ripetizioni:
| Token | Significato | Esempio di corrispondenza |
|---|---|---|
. | Qualsiasi carattere singolo (eccetto newline) | c.t → cat, cut |
\d | Una cifra 0-9 | \d\d → 42 |
\w | Un carattere "word" (a-z, A-Z, 0-9, _) | \w+ → hello_1 |
\s | Spazio bianco (spazio, tab, newline) | — |
[abc] | Uno qualsiasi tra a, b, c | [aeiou] → e |
[^abc] | Qualsiasi carattere eccetto a, b, c | — |
a* | Zero o più a | "", aaa |
a+ | Uno o più a | a, aaa |
a? | Zero o una a (opzionale) | "", a |
a{2,4} | Tra 2 e 4 a | aa, aaaa |
^ / $ | Inizio / fine della stringa | — |
| | Alternativa ("o") | cat|dog → cat o dog |
() | Raggruppamento / cattura | (ab)+ → abab |
Come funzionano le espressioni regolari in PHP
PHP utilizza PCRE (Perl-Compatible Regular Expressions) tramite la famiglia di funzioni preg_. Le più usate:
| Funzione | Cosa fa |
|---|---|
preg_match() | Verifica se un pattern corrisponde; cattura la prima corrispondenza |
preg_match_all() | Trova tutte le corrispondenze in una stringa |
preg_replace() | Sostituisce ogni corrispondenza con un nuovo testo |
preg_split() | Divide una stringa in base a un pattern |
preg_quote() | Escapa i metacaratteri regex in una stringa letterale |
La sintassi di un pattern PHP
Un pattern PHP è una stringa composta da tre parti: un delimitatore, il pattern e modificatori opzionali.
/pattern/modifiersIl primo carattere è il delimitatore — quasi sempre /, ma funziona qualsiasi carattere non alfanumerico (#, ~, !). Scegliere un delimitatore che non appare nel pattern evita di doverlo escapare. Ad esempio, il match di un percorso URL è più pulito con #:
"#^/users/\d+$#" // no need to escape the slashesI modifiers sono lettere opzionali dopo il delimitatore di chiusura che cambiano il comportamento del motore:
i— insensibile alle maiuscole:/php/icorrisponde aPHP,Php,php.m— multilinea:^e$corrispondono all'inizio/fine di ogni riga, non solo dell'intera stringa.s— singola riga ("dotall"):.corrisponde anche ai newline.u— tratta il pattern e il soggetto come UTF-8. Usarlo per qualsiasi testo con caratteri non ASCII.x— esteso: gli spazi nel pattern vengono ignorati, permettendo di spaziare e commentare pattern complessi.
Verificare una corrispondenza con preg_match
preg_match() restituisce 1 se il pattern viene trovato, 0 se no, e false in caso di errore. È la scelta giusta per una domanda sì/no come "questa stringa contiene una cifra?"
Il terzo argomento opzionale, $matches, viene riempito con i risultati: $matches[0] è l'intera corrispondenza, e $matches[1], $matches[2], … sono i gruppi di cattura in ordine — le sottostringhe catturate da ogni coppia di parentesi.
Validare l'input dell'utente
Un uso comune delle regex è la validazione dell'input dell'utente — verificare che un valore abbia la forma corretta prima di memorizzarlo o fidarsi di esso. Ecco un controllo base per l'email:
<?php
$email = "[email protected]";
if (preg_match("/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/", $email)) {
echo "Valid email address";
} else {
echo "Invalid email address";
}
?>Le ancore ^ e $ sono importanti qui: senza di esse il pattern corrisponderebbe a un'email all'interno di una stringa più grande, quindi "junk [email protected] junk" passerebbe la verifica. Con esse, l'intera stringa deve essere una singola email.
Per le email in particolare, la funzione integrata di PHP filter_var() con FILTER_VALIDATE_EMAIL è più robusta di una regex scritta a mano. Ricorrere alle regex quando si ha bisogno di un formato non coperto dai filtri — codici postali, ID personalizzati, formati di numeri di telefono. Vedi validazione dei form PHP per un esempio completo di controllo dell'input.
Trovare tutte le corrispondenze con preg_match_all
Mentre preg_match() si ferma alla prima corrispondenza, preg_match_all() le raccoglie tutte — utile per estrarre ogni hashtag, prezzo o link da un blocco di testo.
<?php
$text = "Prices: $12, $7 and $349";
preg_match_all("/\\\$(\d+)/", $text, $matches);
print_r($matches[1]); // the captured numbers
?>$matches[1] contiene un array di ogni gruppo catturato — in questo caso, ["12", "7", "349"].
Sostituire testo con preg_replace
preg_replace() sostituisce ogni corrispondenza. Nella stringa di sostituzione, $1, $2, … si riferiscono ai gruppi catturati, quindi è possibile riscrivere oltre che rimuovere:
<?php
$date = "2026-06-21";
// Reformat YYYY-MM-DD into DD/MM/YYYY
echo preg_replace("/(\d{4})-(\d{2})-(\d{2})/", "$3/$2/$1", $date);
// 21/06/2026
?>Per dividere una stringa in parti in base a un pattern invece di sostituire, si usa preg_split() — ad esempio dividendo su qualsiasi sequenza di spazi bianchi con /\s+/.
Tecniche avanzate
Una volta acquisita familiarità con le basi, queste funzionalità gestiscono pattern più complessi:
- Gruppi di cattura
(...)— estraggono parti specifiche di una corrispondenza, come mostrato sopra con$matches[1]. - Gruppi non di cattura
(?:...)— raggruppano senza occupare uno slot in$matches, quando serve solo il raggruppamento per un quantificatore o un'alternativa. - Gruppi nominati
(?<year>\d{4})— riferimento a una corrispondenza per nome ($matches['year']) invece che per numero. - Lookahead
(?=...)e lookbehind(?<=...)— corrispondono in base a ciò che segue o precede, senza consumarlo. Utile per "un numero seguito dapx" senza catturarepx. - Quantificatori lazy
*?,+?— corrispondono al minor numero possibile di caratteri. Per default.*è greedy e cattura tutto ciò che può.
Una nota sull'escaping: caratteri come ., +, *, ?, (, ), [, \ hanno un significato speciale. Per corrisponderli letteralmente, anteporre una barra rovesciata (\. corrisponde a un punto letterale). Quando il testo letterale proviene da una variabile, usare preg_quote() per escaparlo in modo sicuro.
Errori comuni
- Dimenticare i delimitatori. I pattern PHP sono stringhe e devono includere i delimitatori:
"/\d+/", non"\d+". Ometterli genera un avviso e la corrispondenza fallisce. - Doppio escaping nelle stringhe con doppi apici. All'interno di
"...", una barra rovesciata è anche un escape PHP."/\d/"funziona perché\dnon è un escape PHP, ma per corrispondere a un$letterale serve"/\\$/". Le stringhe con apici singoli ('/\d/') evitano questa sorpresa. - Il matching greedy cattura troppo.
<.*>su<a><b>corrisponde all'intero<a><b>, non solo a<a>. Usare il lazy<.*?>oppure una classe negata<[^>]*>. - Omettere il modificatore
uper UTF-8. Senza/u,.e\woperano sui byte, danneggiando i caratteri multi-byte.
Conclusione
Le espressioni regolari permettono di descrivere la forma del testo piuttosto che il suo contenuto esatto, rendendole indispensabili per validare l'input, estrarre dati e trasformare stringhe. In PHP si utilizzano tramite le funzioni preg_: preg_match() e preg_match_all() per cercare, preg_replace() per riscrivere, e preg_split() per dividere le stringhe. Si inizia con ancore, classi di caratteri e quantificatori, poi si aggiungono gruppi e lookaround man mano che i pattern crescono. Per approfondire le stringhe su cui si lavora, vedi PHP Strings.