Esempi di Regular Expressions in PHP con preg_match

Introduzione alle regular expressions con l'istruzione preg_match di PHP.

Categoria: PHP | Livello: Beginner | Tags: regex. Scritto da il . Ultimo aggiornamento: 2014-11-15.

Abstract

La funzione preg_match di PHP effettua il riconoscimento di una stringa all'interno di un'altra stringa tramite un criterio espresso con il linguaggio delle espressioni regolari. Gli esempi inclusi in questo articolo mostrano come usare la potenza delle regex per risolvere problemi di varia natura.

1. Come individuare in un testo parole di 4 lettere

In questo esempio utilizzeremo la funzione preg_match all'interno di uno script PHP per individuare le parole di 4 lettere contenute in un testo.

L'espressione regolare per individuare le parole di 4 lettere è: \b[a-z]{4}\b

La sintassi prevede di inserire la regex tra delimitatori (per il delimitatore si usa lo slash: / ) e passare all'interno della funzione sia la regex sia il testo in cui cercare. Per questo motivo nel nostro script PHP definiamo due variabili $regex e $testo alle quali assegnamo i valori desiderati. Con un if stampiamo poi un messaggio che ci fornisce il risultato.

Il codice è:

<?php
$regex = "/\b[a-z]{4}\b/";
$testo = "Questo testo contiene un numero di otto parole";
if (preg_match($regex, $testo)) echo'Risultato: ho trovato almeno una parola di 4 lettere!';
else echo 'Risultato: non ho trovato parole di 4 lettere.';
?>
Nota sulla sintassi di preg_match: si notino i due slash nella stringa $regex, che delimitano il criterio di ricerca stabilito nella regex.

Il risultato dello script:

Risultato: ho trovato almeno una parola di 4 lettere!

La parola di 4 lettere è "otto". Per fugare dubbi sulla possibilità che abbia riconosciuto una sequenza di 4 lettere in una parola di 5 o più lettere, rifacciamo il test modificando la stringa $testo in modo che non contenga parole di 4 lettere:

<?php
$regex = "/\b[a-z]{4}\b/";
$testo = "Questo testo non contiene parole di quattro lettere";
if (preg_match($regex, $testo)) echo'Risultato: ho trovato almeno una parola di 4 lettere!';
else echo 'Risultato: non ho trovato parole di 4 lettere.';
?>

Ecco il risultato dello script modificato:

Risultato: non ho trovato parole di 4 lettere.

2. Come individuare parole di n lettere in un testo caricato via form

Nel primo esempio potevamo trovare soltanto parole di 4 lettere all'interno di un testo predefinito: bene per capire ma poco utile sul piano pratico. Facciamo un passo in avanti e proviamo a cercare parole di un numero n di lettere (a piacere) all'interno di un qualunque testo. Per questo esempio useremo due campi di input: un tipo number per specificare il numero di lettere e un tipo textarea per il testo.

Cerca parole di n lettere all'interno di un testo


In questo secondo esempio il codice del form si trova all'interno di questa pagina, mentre il PHP con la regex è stato inserito in un file esterno. Ecco il PHP con la regex:

<?php
$num_letters = $_POST['num_letters'];
$testo = $_POST['txt_input'];
$regex = "/\b[a-z]{" . $num_letters . "}\b/";
if (preg_match($regex, $testo)) $messaggio = 'Risultato: ho trovato almeno una parola di ' . $num_letters . ' lettere!';
else $messaggio = 'Risultato: non ho trovato parole di ' . $num_letters . ' lettere.';
exit($messaggio);
?>

num_letters e txt_input sono relativi ai campi di input "Numero di lettere" e "Testo in cui cercare".

Nonostante questa pagina di esempi sia dedicata alle regex in PHP con preg_match, ecco anche il codice del form in HTML5:

<form method="post" action="/script/php/strnlett.php">
    <fieldset>
        <legend>Cerca parole di n lettere in un testo</legend>
        <div>
            <label for="num_letters" required>Numero di lettere</label><br/>
            <input type="number" id="num_letters" name="num_letters">
        </div>
        <div>
            <label for="txt_input" required>Digita il testo in cui cercare</label><br />
            <textarea id="txt_input" name="txt_input"></textarea>
        </div>
        <input type="submit" name="cerca" value="Cerca!">
    </fieldset>
</form>

3. Ricerche con numeri e lettere case insensitive

Modifichiamo il codice del primo esempio per fare in modo che la regex ci aiuti a individuare parole che includono anche i numeri, oltre alle lettere; immaginiamo inoltre di volere individuare parole con maiuscole e/o minuscole. Scriviamo quindi una regex che individui parole che abbiano sia cifre sia lettere (e non soltanto gli uni o le altre).

<?php
$regex = "/\b[a-z]+[0-9]+\b/i";
$testo = "Il mio sogno? Percorrere la Route66 da Chicago a Santa Monica a bordo di una Harley-Davidson.";
if (preg_match($regex, $testo)) echo'Risultato: ho trovato almeno una parola con le caratteristiche specificate.';
else echo 'Risultato: non ho trovato parole con le caratteristiche specificate.';
?>

I gruppi [a-z] e [0-9] indicano rispettivamente le lettere dalla a alla z e le cifre (numeri interi) dal 0 al 9. Il segno + è un quantificatore che va letto come "uno o più di uno", riferito all'oggetto che lo precede. Il simbolo i alla fine attiva l'opzione case insensitive, cioé considera lettere maiuscole e minuscole indifferentemente.

Guardiamo lo script all'opera:

Risultato: ho trovato almeno una parola con le caratteristiche specificate.
Nota sull'opzione case insensitive: è stato possibile individuare "Route66", che ha la prima lettera in maiuscolo, grazie alla i posta alla fine della regex.

Il riscontro è positivo grazie alla presenza di "Route66" nel testo. In verità la famosa Historic Route 66 si scrive con "Route" staccato da "66". Proviamo a correggere la regex prevedendo una parola di sole lettere (minimo3) con a seguire uno spazio (facoltativo) e un numero.

<?php
$regex = "/\b[a-z]{3}[a-z]*\s?[0-9]+\b/i";
$testo = "Il mio sogno? Percorrere la Route66 da Chicago a Santa Monica a bordo di una Harley-Davidson.";
if (preg_match($regex, $testo)) echo'Risultato: ho trovato almeno una parola con le caratteristiche specificate.';
else echo 'Risultato: non ho trovato parole con le caratteristiche specificate.';
?>

Adesso controlliamo:

Risultato: ho trovato almeno una parola con le caratteristiche specificate.
Nota sui quantificatori: [a-z]{3} specifica che vogliamo esattamente 3 lettere, [a-z]* che alle prime 3 lettere ne possono seguire altre (* sta per "zero o più" oggetti come quelli che precedono il simbolo), \s indica lo spazio e quindi \s? indica "zero o uno" spazi, [0-9]+ indica "una o più" cifre.

I più attenti avranno notato che nel testo abbiamo caricato comunque "Route66" tutto attaccato, ovviamente di proprosito: con la regex dobbiamo infatti prevedere anche le possibili varianti, ed è per questo che lo spazio va inserito come facoltativo, quindi con \s?. Se avessimo voluto prevenire errori di battitura avremmo potuto inserire l'asterisco * al posto del punto interrogativo ?: in questo modo avremmo accettato anche più d'uno spazio tra l'insieme delle lettere e quello delle cifre.