H2 - P2019

Développement web

Cours 27 - 2016-03-21

PHP

Regex

A.K.A.

  • regexp
  • regular expression
  • rational expression
  • expression régulières
  • expression relationnelles

Chaîne de caractères appelée motif (pattern) permettant de faire une recherche dans une autre chaîne de caractères

Utilité

  • Url Rewriting
  • Tester des données (email, complexité mot de passe, numéro de téléphone, ...)
  • Reformater du texte (BBcode)

Il existe deux types de regex

  • POSIX : lent et légèrement plus facile
  • PCRE : rapide et légèrement plus difficile

Nous utiliserons PCRE

Pour bien démarrer, nous n'allons utiliser que la fonction preg_match()

preg_match() va tester si notre regex "se trouve" dans la chaîne de caractères


// Ce code ne fonctionnera pas
if(preg_match('regex','chaine de caractères'))
    die('vrai');
else
    die('faux');
                    

/Délimiteurs/

  • Les délimiteurs permettent de définir le début et la fin de notre regex
  • On utilise en général / ou #
  • Celui d'ouverture doit être le même que celui de fermeture

preg_match('/regex/','chaine de caractères');
                    
/regex/ voici ma regex vrai
/regex/ voici ma régex faux
/regex/ voici ma regexp vrai
/regex/ voici ma Regex faux
/coucou/ voici ma regex faux

Ou |

  • | appelé pipe correspond à un ou

preg_match('/bonjour|hello/','bonjour tout le monde');
                    
/bonjour|hello/ bonjour tout le monde vrai
/coucou|hello/ bonjour tout le monde faux
/hello|  bonjour/ bonjour tout le monde faux
/a|b|c/ bonjour tout le monde vrai

Début ^ et fin $

  • Il est possible de spécifier si le motif doit se trouver au début et/ou à la fin de la chaîne
  • ^ pour le début
  • $ pour la fin

preg_match('/^bonjour/','bonjour tout le monde');
preg_match('/monde$/','bonjour tout le monde');
                    
/^bonjour/ bonjour tout le monde vrai
/monde$/ bonjour tout le monde vrai
/^bonjour tout le monde$/ bonjour tout le monde vrai
/^bonjour$/ bonjour tout le monde faux

Classes de caractères []

  • Tester un panel de caractères : [abc]
  • Tester l'inverse d'un groupement de caractères : [^abc]
  • Tester une plage de caractères : [a-z] ou [A-Z] ou [0-9]
  • Combiner tout ça : [^a-dA-Z048!]

preg_match('/[a-zA-Z0-1]/','bonjour tout le monde');
                    
/[a]/ bonjour faux
/[ab]/ bonjour vrai
/[^a-z0-9]/ bonjour faux
/^[^a-z]/ Bonjour vrai

Options

  • Il est possible de rajouter des options après le délimiteur de fermeture
  • Il en existe plusieurs, mais celle qu'on utilise le plus est i et permet de rendre la regex insensible à la casse
  • Le reste des options est disponible ici http://www.expreg.com/options.php

preg_match('/^bonjour/i','Bonjour tout le monde');
                    

Quantificateurs ?+*{}

Il est possible de spécifier le nombre d'occurences attendu

  • ? : 0 ou 1 fois
  • * : 0 à plusieurs fois
  • + : Minimum 1 fois
  • {3} : 3 fois
  • {3,10} : 3 à 10 fois
  • {3,} : Minimum 3 fois

preg_match('/o{3}/','booonjour tout le monde');
                    
/o{3}/ booonjour tout le monde vrai
/o{4}/ booonjour tout le monde faux
/a?/ bonjour vrai
/^ba+h$/ baaaaaah vrai
/a{2,4}/ aaaaaaaaa vrai
/^a{2,4}$/ aaaaaaaaa faux

Les groupements ()

  • Il est possible de faire des groupes dans une regex avec ()
  • Cela permet, par exemple, d'utiliser des quantifieurs sur une suite de caractères

preg_match('/(bla){2,}/','blablablabla');
                    
/bla{2,}/ blablablabla faux
/(bla){2,}/ blablablabla vrai
/(bla|blo){2,}/ blablabloblo vrai
/(bl[ao]+){2,}/ blaabloooblaaaooo vrai

Les échappées \

  • Les caractères spéciaux tels que ?, *, +, ^, $, ... sont réservés
  • Si vous souhaitez les utiliser, il suffit de les échapper
  • Précédez-les par \

preg_match('/http:\/\//','http://google.com');
                    

Les classes abrégées

Il existe des raccourcis permettant de simplifier nos regex

  • \d : chiffre
  • \D : pas un chiffre
  • \w : caractère normal (lettres, chiffres, tirets, underscore)
  • \W : Inverse d'un caractère normal (espace, ponctuation)
  • \s : espace ou tabulation
  • . : n'importe quel caractère

preg_match('/\w-\d/','foo-10');
                    
/\w/ c vrai
/\w/ ç faux
/\w/ , faux
/\w/ 3 vrai
/\w/ ! faux
/\w-\d/ foo-10 vrai
/\w-\d/ foo-bar faux
/\w\s\w/ foo        bar faux

Il existe d'autres fonctions PHP utilisant les regex

Nous n'allons voir que preg_​match_​all() et preg_​replace()

preg_match_all()

  • Permet d'obtenir toutes les correspondances du motif dans la chaîne de caractères
  • Il faut lui envoyer un tableau de résultats en troisième argument

$matches = array();

preg_match_all('/(lo)(rem) (ipsum|dolores)/','lorem dolores',$matches);

echo '<pre>';
print_r($matches);
echo '</pre>';
                    

Array
(
    [0] => Array
        (
            [0] => lorem dolores
        )

    [1] => Array
        (
            [0] => lo
        )

    [2] => Array
        (
            [0] => rem
        )

    [3] => Array
        (
            [0] => dolores
        )

)
                    

preg_replace()

  • Permet de remplacer la chaîne de caractères selon la regex

// Mettre tous les 'toto' en gras
$text = 'toto tata tutu toto tete toto tata';
$text = preg_replace('/toto/','toto',$text);
                    

// Mettre tous les 'toto' et 'tata' en gras
$text = 'toto tata tutu toto tete toto tata';
$text = preg_replace('/(toto|tata)/','$1',$text);
                    

Quelques classiques

  • /^[a-z0-9_-]{3,16}$/ : Username
  • /^#?([a-f0-9]{6}|[a-f0-9]{3})$/ : Couleur hexa
  • /^[a-z0-9-]+$/ : Slug
  • /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/ : Email

Quelques classiques

  • /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/ : Url
  • /^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/ : HTML tag

Challenge

Terminez ce jeu : Regex Cross­word