HomeDevExpressions régulières PHP : ce qu’il faut savoir

Expressions régulières PHP : ce qu’il faut savoir

Les expressions régulières (aussi appellées regexp [1]) sont l’outil idéal pour manipuler des données. Elles permettent, à partir d’un masque (pattern en anglais), de trouver les différentes parties d’une chaîne de caractères correspondant à ce masque.

Une des utilisations les plus courantes est le contrôle d’informations fournies via un formulaire. Les expressions régulières sont, de plus, présentes dans de nombreux langages tels que Perl, C++, Python… On les utilise même dans les fichiers htaccess [2] ou encore les feuilles de style CSS [3].

Nous allons voir dans ce premier article la syntaxe utilisée pour les masques, ainsi que les différents caractères spéciaux utilisables et leur utilité, puis nous mettrons tout cela en pratique avec quelques exemples.

Syntaxe de base

Pour simplifier, une expression régulière est une suite de caractères normaux et de caractères spéciaux. Cette suite de caractère constitue un masque que l’on va ensuite appliquer à une chaîne pour trouver les occurences correspondant à ce masque.

Les deux premiers caractères spéciaux que nous allons étudier sont le chapeau (^) et le dollar ($) qui indiquent respectivement le début et la fin d’une chaîne de caractère

^blob
Une chaîne de caractère commençant par blob
gulp$
Une chaîne de caractère se terminant par gulp
^texte$
La chaîne texte
texte
Une chaîne de caractère contenant la chaîne texte

Si le masque commence par ^ ou se termine par $, on dit que le masque est ancré.

Nous allons maintenant voir la signification de l’astérisque (*, du signe plus (+) et du point d’interrogation (?) ainsi que les accolades ({ et }).
Les accolades permettent d’indiquer une intervalle d’occurences valides. En voici la syntaxe (Le deuxième chiffre est facultatif) puis quelques exemples :

{nombre d'occurences minimum, nombre d'occurences maximum}

a{3}
Correspond à la chaîne aaa
a{0,2}
Correspond à une chaîne vide, à a, ou encore aa
a{1,}
Correspond à un ou plusieurs a

Les caractère *+ et ? sont une simplification de cette écriture. * correspond à zéro occurences ou plus+ correspond à une occurence ou plus et ? à zéro ou une occurence.
*+ et ? ont donc respectivement la même signification que {0,}, {1,} et {0,1}

ab*
Un a suivi de zéro ou plusieurs b
ab+
Un a suivi de un ou plusieurs b
ab?
Un a suivi de zéro ou un b

Note : Le caractère ? a d’autres significations selon la position dans le masque (nous verrons cela plus loin)

Voyons maintenant le point (.) et la barre verticale (|).
On peut considérer le point comme une sorte de joker, il représente n’importe quel caractère. La barre verticale implique une alternative, une possibilité entre deux choix (le motif à sa gauche et celui à sa droite).

a.?
Un a suivi de zéro ou un caractère quelconque
^.{3}a
Une chaîne commençant par trois caractères quelconque suivis d’un a
a|b
Le caractère a OU le caractère b

Nous allons maintenant voir l’utilisation des parenthèses.
Une séquence de caractère entre parenthèses est appellée sous-masque. Les sous-masques sont pratiques pour délimiter une séquence de caractères particulière, et peuvent être imbriqués. De plus, les sous-masques peuvent être utilisées conjointement avec les caractères signifiant le nombre d’occurences

bonjour|soir
Acceptera les mots bonjour ou soir
bon(jour|soir)
Acceptera les mots bonjour ou bonsoir
php is (cool|funny)
Acceptera la chaîne php is cool ou la chaîne php is funny
mouarf (arf ){0,2}
Acceptera la chaîne mouarfmouarf arf ou mouarf arf arf

Voici un tableau des différents caractères spéciaux et leur utilité :

Tableau des caractères spéciaux
Caractère Utilité
\ Antislashe Caractère d’échappement à usage multiple
^ Accent circonflexe Représente le début d’une chaîne de caractères (ou d’une ligne si l’option m est active)
$ Dollar Représente la fin d’une chaîne de caractères (ou d’une ligne si l’option m est active)
| Barre verticale Opérateur d’alternative entre l’élément de gauche et celui de droite
. Point Remplace n’importe quel caratère, hormis un saut de ligne (sauf si l’option s est active)
* Astérisque Nombre d’occurence de zéro ou plus du caractère ou de la séquence de caractère qui le précède
+ Signe plus Nombre d’occurence de un ou plus du caractère ou de la séquence de caractère qui le précède
? Point d’interrogation Nombre d’occurence de zéro ou un du caractère ou de la séquence de caractère qui le précède
{ } Accolades spécifient un intervalle de nombre d’occurences du caractère ou de la séquence de caractère qui le précède
( ) Parenthèses Respectivement ouverture et fermeture d’un sous-masque ou séquence de caractères
[ ] Crochets Respectivement ouverture et fermeture d’une classe de caractères

Note : Pour utiliser dans une expression régulière un caractère spécial pour ce qu’il représente, vous devez l’échapper à l’aide d’un antislashe.

Classes de caractères

Une classe de caractères est une liste de caractères potentiels. La classe de caractère remplace uniquement un caractère dans le masque (sauf indication contraire avec en spécifiant le nombre ou l’intervalle de nombre d’occurences). Dans une classe, le signe moins (-) devient un caractère spécial s’il n’est pas au début ou à la fin de la classe de caractère et peut alors désigner une intervalle de caractères. De plus, si vous placez un accent circonflexe au début de la classe, c’est alors une classe d’exclusion (pas ce ou ces caractère)

a[b-d]
Désigne une chaine contenant a suivi de bc ou d
^a[b-d]{1,3}
Désigne une chaine commençant par a suivi de un à trois caractères qui soient bc ou d
a[^0-9]+$
Une chaîne se terminant par a suivi d’un ou plusieurs caractères autre qu’un chiffre

Note : On aurait pu utiliser à la place de [b-d] la séquence (b|c|d), cependant, cela se révèle vite ingérable avec de grands intervalles de caractères, et, de plus, c’est moins optimal qu’une classe de caractères.

Note : Dans une classe de caractères, les caractères spéciaux (tableau précédent) perdent leur capacité spéciale hormis les caractères suivants :

Tableau des caractères spéciaux dans une classe
Caractère Utilité
\ Antislashe Caractère d’échappement à usage multiple
^ Accent circonflexe Placé en premier dans la classe, signifie une classe d’exclusion
] Crochet fermant Termine la classe de caractère
- Signe moins Spécifie un intervalle de caractères sauf si placé au début ou à la fin de la classe

Si vous désirez utiliser le crochet fermant (]) ou le signe moins (-) dans une classe de caractère autrement que pour leur capacité spéciale, vous devez les échapper avec un antislashe ou les placer en premier dans la classe de caractère (ou en dernier pour le signe moins).
Voici quelques autres exemples :

[.$?+*]
Une classe contenant des caractères qui auraient une capacité spéciale en dehors de cette classe
[]a-z-]
Un exemple de classe comprenant les caractères ] et - (le dernier de la classe) simplement pour ce qu’ils sont
[^a-d]
N’importe quel caractère qui n’est ni a, ni b, ni c, ni d

Il existe en outre de nombreux intervalles de caractères prédéfinies. Les voici :

Tableau des intervalles de caractères prédéfinies
Noms de l’intervalle Description
[:alnum:] Tout caractère alphanumérique; équivaut à a-zA-Z0-9
[:alpha:] Tout caractère alphabétique, équivaut à a-zA-Z
[:blank:] Tout caractère blanc (espacement, tabulation…)
[:digit:] Tout caractère numérique, équivaut à 0-9
[:punct:] Tout caractère de ponctuation
[:space:] Caractère d’espacement
[:xdigit:] Tout caractère héxadécimal; équivaut à a-fA-F0-9
[:ctrl:] Tout caractère de contrôle
[:print:] Tout caractère imprimable (hormis les caractères de contrôle)

Exemples concrets d’expressions régulières

Exemple n°1 : Valider un mot de passe

Pour construire un masque valide, il va nous falloir résonner de façon logique. Se poser la question : « A quoi je peux m’attendre précisément ? »
Dans le cas d’un mot de passe par exemple, nous n’allons valider que les mots contenant des caractères alphanumériques, le signe moins ou underscore (_) et comportant au moins 4 caractères et au maximum 32 caractères.
Cela nous donnerait donc comme masque :

^[[:alnum:]_-]{4,32}$

Mise en pratique :

<?php
if( ereg('^[[:alnum:]_-]{4,32}$', $pass) )
{
    echo 'Mot de passe valide';
}
else
{
    echo 'Mot de passe non valide';
}
?>

Exemple n°2 : Valider une URL

Nous allons maintenant construire un masque qui nous permettra de vérifier l’adresse web d’un site.
Pour commencer, l’adresse d’un site doit commencer par http:// :

^http://

Cependant, certains sites sont sécurisés et leur adresse commence donc par https://
Intégrons cela dans notre masque :

^http(s)?://

C’est un bon début, mais on peut faire bien mieux !
Nous allons ajouter une classe de caractère pour ce qui suit //, cela peut être www mais aussi le nom d’un sous domaine. Un nom de domaine (de même qu’un sous domaine) peut être constitué de lettres, de chiffres ou du signe moins.

^http(s)?://[-[:alnum:]]+\.[-[:alnum:]]+

Ajoutons maintenant l’extension du domaine (.com, .net, etc…); elle ne peut être constituée que de lettres et de 2 à 4 caractères.

^http(s)?://[-[:alnum:]]+\.[-[:alnum:]]+\.[a-zA-Z]{2,4}

Enfin, l’adresse peut également contenir un numéro de port :

^http(s)?://[-[:alnum:]]+\.[-[:alnum:]]+\.[a-zA-Z]{2,4}(:[0-9]+)?$

Voila, nous avons maintenant un masque valide pour vérifier la validité syntaxique d’une adresse web entrée dans un formulaire (ex: inscription à un espace membre). Remarquez les caractères de point échappés avec un antislashe.
Le masque peut encore être amélioré bien sûr, par exemple, en sachant qu’un nom de domaine (sans www. ni l’extension) ne peut faire que 63 caractères maximum, ou encore qu’un nom de domaine ne peut ni commencer, ni finir par un tiret.
Mise en pratique :

<?php
$string = 'https://www.phpcodeur.net';
if( ereg('^http(s)?://[-[:alnum:]]+\.[-[:alnum:]]+\.[a-zA-Z]{2,4}(:[0-9]+)?$', $string) )
{
    echo 'Adresse web valide';
}
else
{
    echo 'Adresse web non valide';
}
?>

Conclusion

Nous avons donc eu un aperçu des puissantes possibilités des expressions régulières. Elles peuvent être utiles en maintes occasions, et parfois, être indispensables. Si on ajoute à cela que les expressions sont utilisées de façon universelles, apprendre leur mécanisme constitue presque un passage obligé.

Nous verrons dans la prochaine partie les différentes fonctions php utilisant les regex. Et nous aborderons également le principe des sous-masques capturants, l’utilisation des caractères ‘invisibles’, les différents options de recherche disponibles, ainsi que les références arrières qui peuvent s’avérer très pratique dans certains cas.

Enfin, dans la troisième partie, nous tenterons de prendre le taureau par les cornes en nous attaquant aux assertions, aux sous-masques uniques ou conditionnels, la possibilité de placer des commentaires au sein des masques complexes, et enfin les masques récursifs.

Liens connexes

  • Manuel php : Syntaxe des masques
  • [1] : Le mot Regexp est une contraction de Regular expressions, on utilise aussi parfois le mot Regex
  • [2] : Lorsque l’on veut appliquer des directives de redirection avec RedirectMatch par exemple, ou encore en utilisant le mod_rewrite et la réécriture d’URL
  • [3] : De façon tout à fait minime avec les sélecteurs de type a[hreflang|="en"], mais d’autres choses tout à fait passionnantes nous attendent avec les CSS de niveau 3 🙂

    1 Comment

    1. bonjour Maximilien !
      je suis N’guessan étudiant en informatique développement d’application ,originaire de la Côte d’ivoire.

      j’aime ce que vous faite comme travail .
      alors je me demandais ,étant donné que je suis développeur free-lance ,s’il n’étais pas possible de travailé avec vous !

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

    Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

    PHP Codeur