Principe

  • Les expressions régulières sont des modèles créés à l'aide de caractères ASCII permettant de manipuler des chaînes de caractères et de trouver les portions de la chaîne correspondant au modèle.
  • Ce système vient de POSIX (norme à l'origine sous Unix). De nombreux scripts sous UNIX les utilisent.
  • Les expressions régulières permettent de rechercher des occurrences (= suite de caractères correspondant à ce que l'on recherche) grâce à une série de caractères spéciaux. L'expression régulière en elle-même est donc une chaîne de caractère contenant des caractères spéciaux et des caractères standards

Domaines d'application

  • Vérifier la validité des chaînes de caractères ( saisie dans un formulaire : email, entrée chiffrée, entrée texte, etc...)
  • Extraire des parties bien précises d'une chaîne, d'un texte, d'une page...
  • Modifier une date au format us (05-30-1977) au format fr notamment (30/05/1977)
  • Remplacer automatiquement toutes les adresses "http://" par des liens cliquables (cf forums, guestbook … )
  • Pour créer son propre langage simplifié à partir de la norme HTML, bbCode ([b][/b]...)

Exemple

<?php
if (preg_match("** REGEX **", "string’’)) { echo 'Le mot que vous cherchez se trouve dans la chaîne'; } else { echo 'Le mot que vous cherchez ne se trouve pas dans la chaîne';
} ?> !(((https?|ftp)://(w{3}\.)?)(?<\!www)(\w+-?)*\.([a-z]{2,6}))!

Utilisation

Une regex est toujours entourée de caractères spéciaux appelés délimiteurs.
On peut choisir n'importe quel caractère spécial comme délimiteur, dans les exemples suivant on prendra par convention le délimiteur !
Les délimiteurs permettent d'utiliser des options : '!MA REGEX!Options
Exemple : les expressions régulières sont sensibles à la casse, on peut changer son comportement avec l'option i
Chaîne Test Résultat
J'ai une jolie voiture !jolie! vrai
J'ai une jolie voiture !JOLIE! faux
J'ai une jolie voiture !JOLIE!i vrai

Opérateurs

La barre oblique | signifie ou dans les regex !bleu|rouge!
Les regex permettent des recherches précises et très structurés, dans les exemples précédant le mot pouvait se trouver n’importe ou dans la chaîne
^ (accent circonflexe) : indique le début d'une chaîne. !^Debut!
$ (dollar) : indique la fin d'un chaîne. !fin$!

Entre crochets = la classe de caractères. Cela signifie qu'une des lettres à l'intérieur peut convenir : !gr[aio]s! notre regex reconnaît donc gras gros et gris

Plages de caractères

Grâce au symbole - (le tiret), on peut autoriser toute une plage de caractères.
Si on veut que la chaine contienne une lettre on écrira pas : [abcdefghijklmnopqrstuvwxyz] on peut utiliser les intervalles.
[a-z] ou [a-e] avec les chiffres : [0-9] , [1-8]
On peu combiner les plages aussi : [a-z0-9]. Cela signifie "N'importe quelle lettre (minuscule) OU un chiffre".
On peut aussi autoriser les majuscules, sans passer par les options : [a-zA-Z0-9].
Exemple : !<h[1-6]>! (titres html)

Pour omettre un caractère dans une classe on utilise aussi le symbole ^
Exemple : ![^0-9]! (ne contient aucun chiffre)

Quantificateurs

Les quantificateurs, ce sont des symboles qui permettent de dire combien de fois peuvent se répéter un caractère, ou une suite de caractères.
? (point d'interrogation)
ce symbole indique que la lettre est facultative. Elle peut y être 0 ou 1 fois.
Ainsi, !a?! reconnaît 0 ou 1 "a".
+ (signe plus)
la lettre est obligatoire. Elle peut apparaître 1 ou plusieurs fois.
Ainsi, !a+! reconnaît "a", "aa", "aaa", "aaaa" …
* (étoile)
la lettre est facultative. Elle peut apparaître 0, 1 ou plusieurs fois.
Ainsi, !a*! reconnaît "a", "aa", "aaa", "aaaa" etc... Comme c’est facultatif si a n’y est pas ça renvoi vrai aussi !!!
{n,m}
? correspond à {0,1}
+ correspond à {1,}
* correspond à {0,}
Les quantificateurs s'appliquent à la lettre directement derrière. On peut ainsi autoriser le mot disque qu'il soit au singulier comme au pluriel, avec la regex !disques?!
Pour répéter plusieurs lettres on peut utiliser les parenthèses : !test(test)*! : reconnaitra testtesttesttesttesttesttesttest...

Métacaractères

Ce sont des caractères pas comme les autres qui servent normalement à faire quelque chose de particulier.
les métacaractères qu'il faut connaître sont les suivants :
! ^ $ ( ) [ ] { } ? + * . \
. (point)
remplace n'importe quel caractère (unique)
\ (antislash)
permet d'échapper un métacaractère (ne pas le prendre en compte)

Exemple

Règles

Les règles pour une adresse email valide :
  • On a tout d'abord le pseudonyme (au minimum une lettre). Il peut y avoir des lettres minuscules (pas de majuscules), des chiffres, des points, des tirets et des underscores "_".
  • Il y a ensuite une arobase : @
  • Ensuite il y a le nom du fournisseur d'accès. Pour ce nom, que des minuscules, des chiffres, des tirets, des points et des underscores.
  • Enfin, il y a l'extension (comme ".fr"). Cette extension comporte un point, suivi de 2 à 3 lettres (minuscules).

Construction

  • !^$! Tout d’abord une fin et un début de chaine
  • Ensuite, on a des lettres, chiffres, tirets, points, underscores, au moins une fois. On utilise donc la classe [a-z0-9._-] à la suite de laquelle on rajoute le signe + : !^[a-z0-9._-]+$!
  • l'arobase : !^[a-z0-9._-]+@$!
  • Puis, encore une suite de lettres, chiffres, points, tirets au moins 2 fois : !^[a-z0-9._-]+@[a-z0-9._-]{2,}$!
  • Pour le point de .fr .com … : !^[a-z0-9._-]+@[a-z0-9._-]{2,}\.$!
  • Enfin l’extension (en minuscules) : !^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,6}$!

Recherche / remplacement

preg_replace($masque, $remplacement, $chaine);
Chaque fois qu’on utilisera des parenthèses, ça va créer une "variable" contenant ce qu'elles entourent.
Exemple : !\[b\](.+)\[/b\]! Les parenthèses ici sont inutiles dans le cas d ’une recherche simple, mais pour faire du rechercher remplacer ca va être utile.
A chaque parenthèse ouverte dans une regex, php va créer une variable appelée $1 (pour la première parenthèse), $2 pour la seconde etc…

Exemple

<?php
    $texte = preg_replace('!<b>(.+)</b>!i', '<strong>$1</strong>', $texte);
    ?> 
Premier paramètre la Regex. Attention chaque parenthèse va créer une variable ($1, $2 etc...)
On ajoute l'option "i" pour que le code fonctionne aussi avec des majuscules (<B></B>)
Ensuite on indique le texte de remplacement : "<strong>$1</strong>"
Enfin, dernier paramètre, c'est le texte dans lequel on fait notre recherche / remplacement.

Règles

Avec plusieurs parenthèses, pour savoir le numéro d'une parenthèse il suffit de les compter dans l'ordre de gauche à droite.
Exemple !(anti)co(nsti)(tu(tion)nelle)ment!
Il y a 4 parenthèses dans cette regex (donc $1, $2, $3 et $4). La parenthèse numéro 3 ($3) contient "tutionnelle", et la parenthèse $4 contient "tion"
C ’est l'ordre dans lequel les parenthèses sont ouvertes qui est important.
Les regex sont limitées à 99 parenthèses capturantes dans une Regex $99 est donc la valeur maximum.
Il faut savoir qu ’une variable $0 est toujours créée, elle contient toute la Regex. Sur le même exemple que tout à l'heure : !(anti)co(nsti)(tu(tion)nelle)ment!
$0 contient "anticonstitutionnellement".
Pour ne pas qu ’une parenthèse soit capturante (=pour simplifier les comptes, ou ou si la regex est très complexe), il faut qu'elle commence par un point d'interrogation suivi d'un deux points ?: !(anti)co(?:nsti)(tu(tion)nelle)ment!

Options

Liste non exhaustive :
  • i : pour accepter les majuscules comme les minuscules
  • s : pour que le "point" fonctionne aussi pour les retours à la ligne (pour que le texte puisse être en gras sur plusieurs lignes)
  • U : le U majuscule est une option qui signifie "Ungreedy" ("pas gourmand"). "Ce texte est <b>important</b>, il faut me <b>comprendre</b> !

Exercice

Nous allons réaliser ce qu'on appelle un parser (= "parseur").
Le parser va servir à transformer le texte rédigé par un visiteur (forum / chat / livre d ’or...), en un texte inoffensif mais qui accepte aussi du bbCode !
[b][/b] : pour mettre du texte en gras.
[i][/i] : pour mettre du texte en italique.
[color=red][/color] : pour colorer le texte
Nous ferons en sorte de remplacer aussi automatiquement les URL (http://) par des liens cliquables.

Exercice