PHP (PHP Hypertext Preprocessor)

Auteur: Mohamed CHINY Durée necessaire pour le cours de PHP (PHP Hypertext Preprocessor) Niveau recommandé pour le cours de PHP (PHP Hypertext Preprocessor) Supports vidéo non disponibles pour ce cours Exercices de renforcement disponibles pour ce cours Quiz disponible pour ce cours

Page 17: Expressions régulières

Toutes les pages

Généralités

Une expression régulière est une structure logique connue aussi sous le nom de "model" ou "pattern" qui permet de décrire la forme que doit vérifier une chaîne de caractères. Pour mieux comprendre le principe je vais reprendre le même exemple que nous avons vu en Javascript.

Imaginez qu'on invite un client à saisir une adresse mail dans un champ de saisie. Afin de s'assurer si ce qu'il a entré respecte la forme conventionnelle d'un email, on peut vérifier les points suivants:
  • L'arobas figure-t-il dans l'adresse mail?
  • Y a-t-il un point avant le TLD?
  • Est ce qu'il y a un caractère ou plus avant l'arobas?
  • Le nom de domaine semble-t-il valide?
  • Est ce que l'email ne contient pas de caractères non autorisés comme les espaces?
  • ...

Afin de vérifier tous ces points, on peut faire appel aux fonctions qu'on a déjà vu pour les chaînes de caractères. En les combinant, on pourrait bien se rapprocher de l'objectif. Cependant, le code sera volumineux et, dans la plupart des cas, ne sera pas en mesure de satisfaire à 100% tous les points décrits.

La solution magique consiste donc à faire appel aux expressions régulières.

POSIX et PCRE

En PHP, il existe deux familles d’expressions régulières. Elle font toutes la même chose: chercher des motifs au sein d'une chaîne de caractères. Bien qu'il partagent des fois les mêmes caractères spéciaux au sein des models, il existe quand même de nettes différences entre les deux. Ces deux familles sont:
  • POSIX: il s'agit d'une famille d'expressions régulières utilisée en PHP. POSIX est l'acronyme de Portable Operating System Interface.
  • PCRE: signifie Perl Compatible Regular Expressions. C'est une famille d'expression régulières qui vient du langage PERL.

La principale différence entre les deux familles c'est le temps d’exécution. En effet, les PCRE sont plus rapides que les POSIX, surtout quand il s'agit d'expressions régulières longues et complexes. Une autre différence se manifeste dans la syntaxe. Bien que la plupart des caractères spéciaux des expressions peuvent être utilisés pour les deux familles. Il en existe qui sont propres à chaque famille.

Expressions régulières POSIX

Les fonctions

Les fonctions qui traitent les expressions régulières de la famille POSIX les plus courantes sont: ereg(), mb_ereg(), ereg_replace(), mb_ereg_replace(), split() et mb_split().

  • Fonctions ereg() et eregi():

  • La fonction ereg($motif,$chaine) permet de vérifier l'existence du motif $motif dans la chaîne de caractères $chaine. La variable $motif représente l'expression régulière ou le model à vérifier. La fonction ereg() retourne true si le motif existe dans la chaîne ou false si le motif n'est pas trouvé.

    Exemple:
    <?php
       $str="Bonjour";
       if(ereg("^B",$str))
          echo "La chaîne commence par B";
       else
          echo "La chaîne ne commence pas par B";
    ?>
    On obtient le résultat:
    La chaîne commence par B
    En effet, le motif dit bien que la lettre B doit figurer au début de la chaîne (symbole ^).

    La fonction eregi() fait le même traitement que ereg() mais ne vérifie pas la casse (elle ne différencie pas entre minuscules et majuscules au sein des motifs).
    Notez que les fonctions ereg() et eregi() sont obsolètes.

  • Fonctions mb_ereg() et mb_eregi():

  • La fonction mb_eregi($motif,$chaine) fait le même traitement que la fonction ereg(). Cependant, elle permet de supporter les expressions régulières qui font appel à des caractères multi-octes (multi byte).

    La fonction mb_eregi() ne vérifie pas la casse.

  • Fonctions ereg_replace() et eregi_replace():

  • La fonction ereg_replace($motif,$remp,$chaine) permet de chercher l'expression $motif dans la chaîne de caractères $chaine et le remplacer par $remp.

    Exemple:
    <?php
       $str="Bonjour";
       echo ereg_replace("jour$","soir",$str);
    ?>
    On obtient le résultat:
    Bonsoir
    En fait, le motif "jour" est remplacé par "soir" dans le chaîne "Bonjour". Le dollars ($) après "jour" signifie que le motif doit figurer à la fin de la chaîne.
    Notez que les fonctions mb_ereg() et mb_eregi() sont obsolètes.
    La fonction eregi_replace() fait le même traitement que ereg_replac() mais ne vérifie pas la casse.

  • Fonctions mb_ereg_replace() et mb_eregi_replace():

  • La fonction mb_ereg_replace($motif,$remp,$chaine) fait le même traitement que la fonction ereg_replace() avec le support des caractères multi-octets.

    La fonction mb_eregi_replace() ne vérifie pas la casse.

  • Fonctions split() et spliti():

  • La fonction split($motif,$chaine) permet de découper la chaîne de caractères au niveau des occurrences $motif. Les morceaux de la chaîne seront ensuite stockés dans un tableau. Son fonctionnement rappelle celui de la fonction explode(). Cependant, split() prend en charge les expressions régulières.

    Exemple:
    <?php
       $str="Bonjour";
       $tab=split("o",$str);
       print_r($tab);
    ?>
    Ce qui donne:
    Array ( [0] => B [1] => nj [2] => ur )
    La chaîne est découpée au niveau des caractères "o". On aurait pu faire ce traitement à l'aide de la fonction explode() car nous n'avons pas réellement évoqué une expressions régulière proprement dite.

    La fonction print_r(), dans ce cas, permet d'afficher le contenu d'un tableau avec les indexes associés.

    La fonctin spliti() ne vérifie pas la casse.

  • Fonction mb_split():

  • La fonction mb_split($motif,$chaine) permet de faire le même traitement que la fonction split() avec un support des caractères multi-octets.
    La fonction mb_spliti() n'existe pas.

    Caractères spéciaux d'une expression régulière

    Au sein d'une expression régulière, certains caractères sont considérés comme tels et d'autre sont des caractères spéciaux que la fonction évalue. Voici la liste des caractères spéciaux souvent utilisés:

    caractères spécialSignification
    .Un seul caractère quelconque
    +Le motif précédent doit figurer au moins une fois, le max n'est pas déterminé
    *Le motif précédent doit figurer au moins 0 fois, le max n'est pas déterminé
    ()Pour grouper un ensemble de caractères en tant que motif unique
    []Pour désigner un ensemble de motifs dont , au moins, l'un d'entre eux doit figurer
    -Désigne un intervalle s'il est déclaré entre les crochets. Exemple: [a-z] signifie l'alphabet minuscule
    ?Le motif précédent doit figurer 0 ou une fois.
    ^Le motif suivant doit figurer au début de la chaîne
    $Le motif précédent doit figurer à la fin de la chaîne
    {}Pour spécifier le minimum et le maximum de fois où l'occurrence doit figurer. Exemple: {1,3} désigne que l'occurrence figure entre 1 et 3 fois.

    Exemple:
    <?php
       $email="user@domaine.tld";
       if(mb_ereg(".+@.+\..+",$email))
          echo "Email valide.";
       else
          echo "Email invalide.";
    ?>
    Ce qui donne:
    Email valide.
    En fait, nous avons spécifié une expression simple pour estimer si l'email est valide ou non. Nous avons juste vérifié s'il y a au moins n'importe quel caractère avant l'arobas, le caractère arobas, au moins n'importe quel caractères entre l'arobas et le point, le caractère point (qu'on a déspécialisé avec l'antislash pour qu'il ne soit pas pris pour un caractère spécial), et en fin, au moins n'importe quel caractère après le point.

    Séquences utiles pour simplifier les expressions régulières POSIX

    Imaginez avec moi si on veut vérifier la présente d'un caractère alphabétique (minuscule ou majuscule) ou caractère numérique au sein d'une chaîne de caractères. Le model contiendra donc quelque chose qui ressemble à [a-zA-Z0-9]. Heureusement, il existe des séquences pratiques pour les expressions régulières de la famille POSIX. Par exemple, le model précédent peut s'écrire [[:alnum:]] .

    Voici la liste des séquences les plus fréquentes:

    SéquenceSignification
    [[:alnum:]] Tous les caractères alphabétiques ou numériques (équivalent à [a-zA-Z0-9])
    [[:alpha:]] Tous les caractères alphabétiques (équivalent à [a-zA-Z])
    [[:digit:]] Tous les caractères numériques (équivalent à [0-9])
    [[:blank:]] Tous les types d'espaces et tabulation
    [[:xdigit:]] Caractères hexadécimaux (équivalent à [a-fA-F0-9])
    [[:graph:]] Tous les caractères affichables et imprimables
    [[:punct:]] Tous les caractères de ponctuation
    [[:cntrl:]] Caractères d’échappement

    Expressions régulières PCRE

    Il s'agit de la famille des expressions régulières la plus recommandée vu sa rapidité surtout lorsqu'il s'agit de motifs complexes.

    Les fonctions

    Nous allons nous intéresser aux fonctions preg_match(), preg_replace() et preg_split().

  • Fonction preg_match():

  • La fonction preg_match($motif,$chaine) peut contenir plusieurs paramètres. Pour simplifier, nous allons nous contenter des deux premiers à savoir, $motif qui désigne l'expression régulière et $chaine qui représente la chaîne de caractères dans laquelle on vérifie la présence du motif.

    Le motif d'une expression PCRE doit toujours être placé entre des délimiteurs de votre choix. Le plus courant c'est d'utiliser un slah ou un dièse.

    Par exemple, si on veut vérifier la présence de l'arobas dans la chaîne $email, alors le code ressemblerait à ceci:
    <?php
       $email="user@domaine.tld";
       if(preg_match("#@#",$email))
          echo "L'arobas existe.";
       else
          echo "L'arobas n'existe pas.";
    ?>
    Ce qui donne:
    L'arobas existe.
    Vous avez remarqué que nous avons placé le motif @ entre deux dièses dans ce cas.

    Imaginons maintenant qu'on veut vérifier si un Email est valide, alors on peut faire ceci:
    <?php
       $email="user@domaine.tld";
       if(preg_match("#^[a-zA-Z0-9-_.]+@[a-zA-Z0-9-.]+\.[a-zA-Z]{2,6}$#",$email))
          echo "Email valide.";
       else
          echo "Email invalide.";
    ?>
    Ce qui donne:
    Email valide.
    En effet, nous estimons qu'un email valide commence par un nom d'utilisateur (qui peut contenir des lettres, chiffres, tirets, sous-tirets ou points), suivi d'un arobas, suivi du nom de domaine (qui peut être constitué de lettres, chiffres, tirets ou points) suivi du point déspécialisé et, en fin, le TLD qui est sensé contenir de 2 à 6 lettres.

    Vous avez donc remarqué que les caractères spéciaux utilisés sont les même que ceux du POSIX.

  • Fonction preg_replace:

  • La fonction preg_replace($motif,$remp,$chaine) permet de chercher le motif $motif dans la chaîne de caractères $chaine et le remplacer par $remp.

    Exemple:
    <?php
       $email="user@domaine.tld";
       echo preg_replace("#.tld$#",".com",$email);
    ?>
    Ce qui donne:
    user@domaine.com
    Nous avons cherché le motif ".tld" à la fin de la chaîne (il faut déspécialiser le point), qu'on a remplacé par ".com" (dans ce cas, le point ne dois pas être déspécialisé car le deuxième paramètre n'est pas une expression régulière).

  • Fonction preg_split:

  • La fonction preg_split($motif,$chaine) éclate la chaîne de caractères $chaine au niveau des occurrences décrits par $motif et dépose les fragments de la chaîne dans un tableau.

    Exemple:
    <?php
       $str="Bonjour";
       $tab=preg_split("#o#",$str);
       print_r($tab);
    ?>
    Ce qui donne:
    Array ( [0] => B [1] => nj [2] => ur )
    La chaîne a été éclatée au niveau des caractères o. On aurait pu avoir le même résultat avec la fonction explode(), sauf que celle ci ne supporte pas des motifs sous forme d'expressions régulières.

    Séquences utiles pour simplifier les expressions régulières PCRE

    Comme pour la famille POSIX, PCRE dispose d'un ensemble de séquences qui permettent de simplifier nettement l'écriture des expressions régulières.

    Ce tableau donne un aperçu sur les séquences les plus courantes:

    SéquenceSignification
    \dTous les chiffres (équivalent à [0-9])
    \DTout ce qui n'est pas un chiffre (équivalent à [^0-9])
    \wTous les caractères alphabétique, numériques ou caractère sous-tiret (équivalent à [a-zA-Z0-9_])
    \WTous les caractères qui ne sont pas alphabétiques, numériques ou caractère sous-tiret (équivalent à [^a-zA-Z0-9_])
    \tTabulation
    \sEspace
    \rRetour chariot
    \nNouvelle ligne