Aller au contenu principal

Les expressions régulières

Cette séance est un approfondissement facultatif mais utile. Les expressions régulières ont la réputation d'être difficiles pour les débutants : prenez votre temps, avancez pas à pas, et n'hésitez pas à relire chaque exemple plusieurs fois.

Notions théoriques

Qu'est-ce qu'une expression régulière ?

Une expression régulière (ou regex) est un motif (un modèle de texte) qui décrit une manière de reconnaître certaines chaînes de caractères. Elle permet de rechercher, tester ou remplacer du texte selon des règles, plutôt que de comparer une chaîne exacte.

Par exemple, plutôt que de vérifier qu'un texte est exactement égal à "0612345678", une expression régulière permet de vérifier que le texte ressemble à un numéro de téléphone : un 0, suivi de 9 chiffres.

info

Souvenez-vous de la séance sur les formulaires (0080_PHP_formulaires) : les expressions régulières servent très souvent à valider ce qu'un utilisateur a saisi (email, mot de passe, numéro de téléphone…) avant de l'enregistrer.

Les délimiteurs en PHP

En PHP, un motif de recherche doit toujours être encadré par des délimiteurs, le plus souvent le caractère /.

$motif = "/php/";

Ce motif recherche la présence exacte du texte "php" dans une chaîne.

remarque

On peut utiliser d'autres délimiteurs que / (par exemple # ou ~), notamment quand le motif contient lui-même des /. Le caractère de début et de fin doit toujours être le même.

Après le délimiteur de fin, on peut ajouter des modificateurs. Le plus courant est i, pour ignorer la casse (majuscules/minuscules) :

$motif = "/php/i"; // trouve "php", "PHP", "Php"...

Classes de caractères et quantificateurs de base

Une expression régulière se construit avec des symboles spéciaux. En voici les plus utiles pour débuter :

SymboleSignification
\dun chiffre (équivalent à 0-9)
\wun caractère "mot" (lettre, chiffre ou _)
\sun espace (espace, tabulation, saut de ligne)
.n'importe quel caractère (sauf saut de ligne)
*l'élément précédent, 0 fois ou plus
+l'élément précédent, 1 fois ou plus
?l'élément précédent, 0 ou 1 fois
{n,m}l'élément précédent, entre n et m fois

Quelques exemples de motifs :

"/\d+/" // un ou plusieurs chiffres à la suite
"/\w+/" // un ou plusieurs caractères de "mot"
"/\d{2,4}/" // entre 2 et 4 chiffres
"/colou?r/" // "color" ou "colour" (le "u" est optionnel)
info

Les symboles ^ et $ sont appelés des ancres : ^ signifie début de chaîne, $ signifie fin de chaîne. /^\d+$/ vérifie que la chaîne entière est composée uniquement de chiffres, du début à la fin.

Tester et capturer avec preg_match()

La fonction preg_match() teste si un motif est présent dans une chaîne. Elle retourne 1 si le motif est trouvé, 0 sinon.

$texte = "Mon numero est 0612345678";

if (preg_match("/\d+/", $texte)) {
echo "Un nombre a ete trouve.";
}

En ajoutant un troisième paramètre, preg_match() remplit un tableau avec le résultat trouvé :

$texte = "Mon numero est 0612345678";

preg_match("/\d+/", $texte, $resultat);
echo $resultat[0]; // 0612345678

On peut aussi capturer une partie précise du motif en l'entourant de parenthèses (...) :

$texte = "Contact : alice@mail.com";

preg_match("/(\w+)@(\w+\.\w+)/", $texte, $resultat);
echo $resultat[0]; // alice@mail.com (la correspondance complète)
echo $resultat[1]; // alice (le 1er groupe capture)
echo $resultat[2]; // mail.com (le 2eme groupe capture)

Remplacer avec preg_replace()

La fonction preg_replace() fonctionne comme str_replace(), mais avec un motif au lieu d'un texte exact.

$texte = "Le prix est 12 euros et 8 centimes";

$texte = preg_replace("/\d+/", "X", $texte);
echo $texte; // "Le prix est X euros et X centimes"

Tous les groupes de chiffres ont été remplacés par "X", quelle que soit leur longueur.

Exemple concret : valider un format d'email

En combinant les ancres, les classes de caractères et les quantificateurs, on peut construire un motif qui valide un format d'email simple :

$email = "alice@mail.com";
$motif = "/^\w+@\w+\.\w+$/";

if (preg_match($motif, $email)) {
echo "Email valide";
} else {
echo "Email invalide";
}

Ce motif se lit ainsi :

  • ^ : début de la chaîne
  • \w+ : un ou plusieurs caractères de mot (la partie avant le @)
  • @ : le caractère @ exact
  • \w+ : un ou plusieurs caractères de mot (le nom de domaine)
  • \. : un point exact (le . doit être "échappé" avec \ car . seul signifie "n'importe quel caractère")
  • \w+ : un ou plusieurs caractères de mot (l'extension, comme "com")
  • $ : fin de la chaîne
attention

Ce motif reste simplifié : il ne gère pas tous les formats d'email valides (par exemple les points ou tirets dans la partie avant le @). En pratique, PHP fournit filter_var($email, FILTER_VALIDATE_EMAIL) pour une validation d'email fiable en production. Les expressions régulières restent néanmoins indispensables pour valider des formats plus spécifiques (numéro de téléphone, code postal, référence produit…).

Exemple pratique

<?php
// Validation d'un numero de telephone francais simple : 0 suivi de 9 chiffres
function validerTelephone($numero) {
$motif = "/^0[1-9](\d{2}){4}$/";
return preg_match($motif, $numero) === 1;
}

$numeros = ["0612345678", "061234567", "abcdefghij", "0712345678"];

foreach ($numeros as $numero) {
if (validerTelephone($numero)) {
echo $numero . " est un numero valide\n";
} else {
echo $numero . " est invalide\n";
}
}

// Masquer les 4 derniers chiffres d'un numero de telephone
$numeroMasque = preg_replace("/\d{4}$/", "****", "0612345678");
echo $numeroMasque; // "061234****"

Le motif "/^0[1-9](\d{2}){4}$/" se lit ainsi :

  • ^0 : la chaîne commence par le chiffre 0
  • [1-9] : suivi d'un chiffre entre 1 et 9 (pas de 0 en deuxième position)
  • (\d{2}){4} : suivi de 4 fois deux chiffres (soit 8 chiffres au total)
  • $ : jusqu'à la fin de la chaîne
astuce

Une expression régulière complexe se comprend mieux si on la découpe morceau par morceau, comme ci-dessus. C'est aussi une bonne pratique à adopter en commentaire dans son code, car une regex se relit rarement facilement plusieurs mois après l'avoir écrite.

Test de mémorisation/compréhension


Qu'est-ce qu'une expression régulière ?


Quel caractère est le délimiteur le plus courant pour un motif en PHP ?


Que représente le symbole \d dans une expression régulière ?


Que représente le symbole \w dans une expression régulière ?


Que signifie le quantificateur + après un symbole ?


Que signifie le quantificateur ? après un symbole ?


Quelle fonction PHP teste si une chaîne correspond à un motif ?


Quelle fonction PHP remplace toutes les correspondances d'un motif dans une chaîne ?


Dans le motif /^\d+$/, à quoi servent les symboles ^ et $ ?


Pourquoi faut-il écrire \. pour représenter un point exact dans une expression régulière ?


Que fait preg_match('/\d+/', $texte, $resultat) après son exécution si $texte contient un nombre ?


Quelle fonction PHP est recommandée en production pour valider un format d'email de façon fiable ?



TP pour réfléchir et résoudre des problèmes

Dans ce TP, vous allez écrire un petit script de validation de formulaire d'inscription, en utilisant les expressions régulières vues dans cette séance.

  • Dans votre répertoire "Documents" créez le répertoire tp_regex.
  • Dans ce répertoire créez le fichier main.php :
    <?php
    // Les expressions regulieres
    print("Les expressions regulieres \n\n");
  • Testez le fonctionnement de ce fichier :
    php main.php

Étape 1 — Écrire un motif pour détecter des chiffres

Écrivez un motif qui recherche un ou plusieurs chiffres à la suite, et stockez-le dans une variable $motif.


Bonne pratique - Nommer clairement ses motifs

Stocker un motif dans une variable bien nommée (comme $motifTelephone plutôt que $motif) rend le code plus lisible, surtout quand plusieurs motifs sont utilisés dans le même script.

Étape 2 — Tester une saisie avec preg_match()

En utilisant preg_match(), testez si la chaîne $pseudo contient au moins un chiffre.


Bonne pratique - Tester avant de valider

Avant d'écrire un motif complexe (comme un email complet), il est utile de tester d'abord un motif simple (comme "contient un chiffre") pour vérifier que l'on comprend bien le comportement de preg_match().

Étape 3 — Capturer une partie du texte

En utilisant des parenthèses de capture, extrayez uniquement les chiffres présents dans la chaîne "Reference produit REF-4521".


Bonne pratique - Vérifier avant d'utiliser une capture

Toujours vérifier que preg_match() retourne 1 avant d'utiliser $resultat[1], sinon PHP peut générer une erreur "Undefined array key" si le motif n'a rien trouvé.

Étape 4 — Remplacer un motif avec preg_replace()

En utilisant preg_replace(), remplacez toutes les suites de chiffres présentes dans une chaîne par le texte "[NOMBRE]".


Bonne pratique - preg_replace() pour anonymiser des données

preg_replace() est souvent utilisé pour anonymiser des données dans des journaux (logs) ou des exemples : remplacer un numéro de carte, un email, ou un numéro de téléphone par un texte générique avant de les afficher ou de les stocker.

Étape 5 — Valider un format d'email

Écrivez une fonction validerEmail($email) qui retourne true si l'email respecte le format texte@texte.texte, false sinon.


Bonne pratique - Comparer avec === plutôt qu'avec if direct

preg_match() peut retourner 0, 1 ou false (en cas d'erreur dans le motif). Comparer explicitement le résultat à 1 avec === évite les confusions liées à la conversion automatique de type en PHP.

Étape 6 — Valider un numéro de téléphone simple

Écrivez une fonction validerTelephone($numero) qui retourne true si le numéro commence par 0, suivi d'un chiffre entre 1 et 9, puis de 8 chiffres (soit 10 chiffres au total).


Bonne pratique - Regex et validation côté serveur

Valider avec une expression régulière côté serveur (en PHP) reste indispensable, même si le formulaire HTML fait déjà une validation côté navigateur : un utilisateur malveillant peut toujours contourner la validation du navigateur en envoyant directement une requête.

Une solution du TP

📌 Une solution