Infocurci - programmatore Php Roma
Infocurci - programmatore Php Roma
Questo sito non lascia nessun cookie sul vostro pc, consuma pochissimi kb, non profila nulla e non raccoglie dati personali. Siete i benvenuti.

Php : Le espressioni regolari con Php - 2. parte

In questa seconda puntata del tutorial dedicato alle espressioni regolari vedremo nuovi caratteri speciali e proveremo ad estrarre da un testo tutti i nomi di persona: una regexp che potrà tornare utile in diverse occasioni.

Php

Iniziamo con un esempio più pratico rispetto al "Lorem ipsum" usato a scopo didattico nella prima puntata. Dato un testo, vogliamo estrarre tutti i nomi propri; di fatto tutte quelle parole che iniziano con la lettera maiuscola. Il testo preso in esame è un caotico tabellino di una partita di basket (l'Italia che vinse l'Europeo 1999), dalla quale vogliamo estrarre solo i nomi dei giocatori, senza le statistiche numeriche.
tabellino: Bonora; Basile 2 (1 / 4, 0 / 1); Galanda 4 (1 / 1, 0 / 1); Fucka 10 (3 / 6, 1 / 1); Marconato 2 (1 / 1); De Pol 7 (1 / 1, 1 / 3); Myers 18 (3 / 6, 0 / 2); Meneghin 2 (1 / 3, 0 / 4); Abbio 10 (1 / 3, 0 / 3); Mian; Chiacig 9 (3 / 5); Damiao.
I problemi da risolvere, rispetto a quanto già sappiamo fare, sono tre:
1) come istruire l'espressione regolare in modo da farle ricercare parole intere, se non sappiamo quanti caratteri può avere un nome? Nella prima lezione avevamo a che fare con parole di 3 lettere, facilmente individuabili dal carattere speciale \w e dal quantificatore {3}; oggi vogliamo trovare delle parole senza sapere però a priori quanto saranno lunghe.
2) come estrarre solo le parole, escludendo quindi i tanti numeri? il caratteri visto finora \w individua alfanumerici, quindi anche numeri...
2) come ricercare solo le parole che iniziano con una lettera maiuscola?
Partiamo dal primo problema, il secondo lo affronteremo a fine articolo. Per estrarre tutte le parole a prescindere dalla loro lunghezza abbiamo bisogno di un quantificatore che chieda all'espressione regolare di trovare "tutte le parole che abbiano 1 o più caratteri". Questo quantificatore è rappresentato dal carattere "+". Proviamo questa istruzione:
<?php
    $testo = 'tabellino: Bonora; Basile 2 (1 / 4, 0 / 1); Galanda 4 (1 / 1, 0 / 1); Fucka 10 (3 / 6, 1 / 1); Marconato 2 (1 / 1); De Pol 7 (1 / 1, 1 / 3); Myers 18 (3 / 6, 0 / 2); Meneghin 2 (1 / 3, 0 / 4); Abbio 10 (1 / 3, 0 / 3); Mian; Chiacig 9 (3 / 5); Damiao.';
    preg_match_all('#\b\w+\b#',$testo,$elenco_parole);
    print_r($elenco_parole);
?>

Benino.. trova tutte le parole ma anche quelle minuscole ("tabellino") e tutti i numeri, sia pur senza le parentesi e gli slash:

Array
(
    [0] => Array
        (
            [0] => tabellino
            [1] => Bonora
            [2] => Basile
            [3] => 2
            [4] => 1
            [5] => 4
            [6] => 0
            [7] => 1
            [8] => Galanda //ecc ecc

Vediamo come risolvere quindi il secondo problema: escludere i numeri. Sostituiamo l'espressione precedente con questa:

    preg_match_all('#\b[a-z]+\b#',$testo,$elenco_parole);
cosa significa [a-z]? Si tratta di un set di caratteri. Abbiamo dato istruzione di trovare tutto ciò che è compreso tra la lettera "a" e la "z", di fatto tutto l'alfabeto; lanciando questa regexp però rimaniamo delusi perché è stata trovata un'unica parola: "tabellino";

Array
(
    [0] => Array
        (
            [0] => tabellino
        )

)

Come mai? [a-z] significa cercare tutto ciò che è compreso tra a e z ma non ciò che è compreso tra A e Z (maiuscolo)! Visto che a noi interessano solo le lettere maiuscole, proviamo il set A-Z:

    preg_match_all('#\b[A-Z]+\b#',$testo,$elenco_parole);
risultato ancora peggiore.. non è stato estratto nulla!
Come mai? Ecco, in questi casi prendetevi i canonici 5 minuti di pausa e iniziate a ragionare in serenità. Ecco la sintassi:
# è l'inizio della regexp, e fin qui ci siamo
\b è il delimitatore di parola, ok
[A-Z] è un set di caratteri che istruisce la regex di trovare il carattere maiuscolo
+ è il quantificatore che gli dice che ciò che sta cercando ([A-Z]) deve esser presente almeno 1 volta
\b è il delimitatore di parola
Ecco l'errore: gli abbiamo detto di cercare una parola composta da uno o più caratteri maiuscoli.. ma non gli abbiamo detto che dopo questi caratteri maiuscoli devono essercene altri minuscoli!
Cambiamo la nostra regexp:
    preg_match_all('#\b[A-Z]+\w+\b#',$testo,$elenco_parole);
E finalmente, ecco l'elenco degli eroi di Parigi 1999!

Array
(
    [0] => Array
        (
            [0] => Bonora
            [1] => Basile
            [2] => Galanda
            [3] => Fucka
            [4] => Marconato
            [5] => De
            [6] => Pol
            [7] => Myers
            [8] => Meneghin
            [9] => Abbio
            [10] => Mian
            [11] => Chiacig
            [12] => Damiao
        )

)

Ecco il riepilogo della regexp:

# è l'inizio della regexp, e fin qui ci siamo
\b è il delimitatore di parola, ok
[A-Z] è un set di caratteri che istruisce la regex di trovare il carattere maiuscolo
+ è il quantificatore che gli dice che ciò che sta cercando ([A-Z]) deve esser presente almeno 1 volta
\w è la classe di caratteri che istruisce la regex di trovare qualsiasi carattere alfanumerico
+ è il quantificatore che gli dice che ciò che sta cercando (\w) deve esser presente almeno 1 volta
\b è il delimitatore di fine parola

In realtà anche qui possiamo trovare una pecca: "De" e "Pol" sarebbe un unico cognome.. ma per quanto riguarda questa lezione, possiamo fermarci qui. Nella prossima puntata, partiremo proprio da questo scenario e vedremo come si affronta di solito un problema del genere.