Les classes de caractères des regex

Dans cette nouvelle leçon, nous allons découvrir les classes de caractères et commencer à créer des masques relativement complexes et intéressants pour nos expressions régulières.

 

Les classes de caractères

Les classes de caractères vont nous permettre de fournir différents choix de correspondance pour un caractère en spécifiant un ensemble de caractères qui vont pouvoir être trouvés. En d’autres termes, elles vont nous permettre de rechercher n’importe quel caractère d’une chaine qui fait partie de la classe de caractères fournie dans le masque.

Pour déclarer une classe de caractères dans notre masque, nous allons utiliser une paire de crochets [ ] qui vont nous permettre de délimiter la classe en question.

Prenons immédiatement un exemple concret en utilisant des classes de caractères simples :

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP & MySQL</title>
        <meta charset="utf-8">
        <link rel="stylesheet" href="cours.css">
    </head>
    
    <body>
        <h1>Titre principal</h1>
        <?php
            $masque1 = '/[aeiouy]/';
            $masque2 = '/j[aeiouy]/';
            $masque3 = '/[aeiouy][aeiouy]/';
            $chaine = 'Bonjour, je suis Pierre';
            
            preg_match_all($masque1,$chaine,$tb1);
            preg_match_all($masque2,$chaine,$tb2);
            preg_match_all($masque3,$chaine,$tb3);
            echo '<pre>';
            print_r($tb1);
            echo '<br><br>';
            print_r($tb2);
            echo '<br><br>';
            print_r($tb3);
            echo '</pre>';
        ?>
        <p>Un paragraphe</p>
    </body>
</html>

 

Présentation et exemple d'utilisation des classes de caractères des expressions régulières PHP

Ici, on utilise différentes classes de caractères dans nos masques pour rechercher différents caractères ou séquences de caractères dans nos chaines.

Notre premier masque est très simple : il contient uniquement la classe de caractères [aeiouy]. Cette classe de caractères va nous permettre de chercher tous les caractères de notre chaine qui sont des voyelles (soit un « a », soit « e », soit « i », soit « o », soit « u », soit « y »).

Notre fonction preg_match_all() va donc ici renvoyer toutes les voyelles de notre chaine une à une.

Notre deuxième masque permet de chercher la séquence « j suivi d’un voyelle ». En effet, ici, on place le caractère « j » en dehors de notre classe de caractères. Le masque va donc nous permettre de chercher des séquences de deux caractères dont le premier est un « j » et le deuxième fait partie de la classe [aeiouy].

Dans notre troisième masque, nous utilisons cette fois-ci deux classes de caractères d’affilée. Ici, les deux classes de caractères sont identiques (on aurait tout-à-fait pu spécifier deux classes de caractères différentes) et vont toutes les deux nous permettre de rechercher une voyelle. On va donc ici pouvoir chercher deux voyelles à la suite.

 

Les classes de caractères et les méta caractères

Dans le langage des expressions régulières, de nombreux caractères vont avoir une signification spéciale et vont nous permettre de signifier qu’on recherche tel caractères ou telle séquence de caractères un certain nombre de fois ou à une certaine place dans une chaine.

Ces caractères spéciaux qu’on appelle des métacaractères vont nous permettre de créer des schémas ou masques de recherche très puissants et donc d’exploiter toute la puissance des expressions régulières. On a pu en voir un premier exemple avec les caractères crochets [ ] qui permettent de définir une classe de caractères.

Au sein des classes de caractères, nous n’avons accès qu’à 3 métacaractères, c’est-à-dire qu’il n’existe que trois caractères qui possèdent un sens spécial lorsqu’ils sont placés tels quels dans une classe de caractères. Ces métacaractères sont les suivants :

MétacaractèreDescription
\Caractère de protection qui va avoir plusieurs usages (on va pouvoir s’en servir pour donner un sens spécial à des caractères qui n’en possèdent pas ou au contraire pour neutraliser le sens spécial des métacaractères).
^Si placé au tout début d’une classe, permet de nier la classe c’est-à-dire de chercher tout caractère qui n’appartient pas à la classe.
Entre deux caractères, permet d’indiquer un intervalle de caractères.

Si on souhaite rechercher le caractère représenté par un métacaractère et qu’on ne souhaite pas utiliser son sens spécial (par exemple si on souhaite rechercher le signe moins), il faudra alors le protéger avec un antislash.

Attention ici : pour rechercher le caractère antislash avec une expression rationnelle (c’est-à-dire à partir d’un masque stocké sous forme de chaine de caractères), il faudra préciser 4 antislashs d’affilée. En effet, l’analyseur PHP va ici considérer les 1er et 3è antislash comme des caractères d’échappement pour les deux autres et ne conserver donc que les 2è et 4è antislash puis la regex va considérer le 1er des deux antislashs restants comme un caractère de protection et va donc rechercher le caractère antislash placé derrière.

Notez qu’il faudra également protéger les signes crochets fermants ainsi que le délimiteur de masque choisi si on souhaite les inclure pour les rechercher dans une classe de caractères car dans le cas contraire le PHP penserait qu’on termine une classe de caractères ou notre masque.

<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP & MySQL</title>
        <meta charset="utf-8">
        <link rel="stylesheet" href="cours.css">
    </head>
    
    <body>
        <h1>Titre principal</h1>
        <?php
            $masque1 = '/[^aeiouy]/';
            $masque2 = '/[\^aeiouy]/';
            $masque3 = '/[aei^ouy]/';
            $masque4 = '/[a-z]o/';
            $masque5 = '/[a-zA-Z]o/';
            $masque6 = '/[a\-z]/';
            $masque7 = '/[0-9az-]/';
            $masque8 = '/[\/[\]\\]/';
            $chaine = 'Bonjour, qui suis-je ? Je suis [Pierre] 
<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP & MySQL</title>
        <meta charset="utf-8">
        <link rel="stylesheet" href="cours.css">
    </head>
    
    <body>
        <h1>Titre principal</h1>
        <?php
            $masque1 = '/[^aeiouy]/';
            $masque2 = '/[\^aeiouy]/';
            $masque3 = '/[aei^ouy]/';
            $masque4 = '/[a-z]o/';
            $masque5 = '/[a-zA-Z]o/';
            $masque6 = '/[a\-z]/';
            $masque7 = '/[0-9az-]/';
            $masque8 = '/[\/[\]\\\\]/';
            $chaine = 'Bonjour, qui suis-je ? Je suis [Pierre] \0/ ^^';
    
            preg_match_all($masque1,$chaine,$tb1);
            preg_match_all($masque2,$chaine,$tb2);
            preg_match_all($masque3,$chaine,$tb3);
            preg_match_all($masque4,$chaine,$tb4);
            preg_match_all($masque5,$chaine,$tb5);
            preg_match_all($masque6,$chaine,$tb6);
            preg_match_all($masque7,$chaine,$tb7);
            preg_match_all($masque8,$chaine,$tb8);
            
            /*Ici, je sais que mes tableaux multidimensionnels ne contiennent
             *qu'un tableau à chaque fois. J'utilise la fonction implode()
             *qui renvoie les éléments d'un tableau sous forme de chaine de
             *caractères séparés par un séparateur choisi (ici la virgule)*/
            echo 'Caractères trouvés (masque 1) : ' .implode(', ', $tb1[0]). '<br>';
            echo 'Caractères trouvés (masque 2) : ' .implode(', ', $tb2[0]). '<br>';
            echo 'Caractères trouvés (masque 3) : ' .implode(', ', $tb3[0]). '<br>';
            echo 'Caractères trouvés (masque 4) : ' .implode(', ', $tb4[0]). '<br>';
            echo 'Caractères trouvés (masque 5) : ' .implode(', ', $tb5[0]). '<br>';
            echo 'Caractères trouvés (masque 6) : ' .implode(', ', $tb6[0]). '<br>';
            echo 'Caractères trouvés (masque 7) : ' .implode(', ', $tb7[0]). '<br>';
            echo 'Caractères trouvés (masque 8) : ' .implode(', ', $tb8[0]). '<br>';
        ?>
        <p>Un paragraphe</p>
    </body>
</html>
/ ^^'; preg_match_all($masque1,$chaine,$tb1); preg_match_all($masque2,$chaine,$tb2); preg_match_all($masque3,$chaine,$tb3); preg_match_all($masque4,$chaine,$tb4); preg_match_all($masque5,$chaine,$tb5); preg_match_all($masque6,$chaine,$tb6); preg_match_all($masque7,$chaine,$tb7); preg_match_all($masque8,$chaine,$tb8); /*Ici, je sais que mes tableaux multidimensionnels ne contiennent *qu'un tableau à chaque fois. J'utilise la fonction implode() *qui renvoie les éléments d'un tableau sous forme de chaine de *caractères séparés par un séparateur choisi (ici la virgule)*/ echo 'Caractères trouvés (masque 1) : ' .implode(', ', $tb1[0]). '<br>'; echo 'Caractères trouvés (masque 2) : ' .implode(', ', $tb2[0]). '<br>'; echo 'Caractères trouvés (masque 3) : ' .implode(', ', $tb3[0]). '<br>'; echo 'Caractères trouvés (masque 4) : ' .implode(', ', $tb4[0]). '<br>'; echo 'Caractères trouvés (masque 5) : ' .implode(', ', $tb5[0]). '<br>'; echo 'Caractères trouvés (masque 6) : ' .implode(', ', $tb6[0]). '<br>'; echo 'Caractères trouvés (masque 7) : ' .implode(', ', $tb7[0]). '<br>'; echo 'Caractères trouvés (masque 8) : ' .implode(', ', $tb8[0]). '<br>'; ?> <p>Un paragraphe</p> </body> </html>

 

Présentation et exemple d'utilisation des métacaractères des expressions régulières PGP

Ici, nous avons créé 8 masques différents. Le premier masque utilise le caractère ^ en début de classe de caractère. Ce caractère va donc être interprété selon son sens de métacaractère et va nier la classe. Notre masque va donc nous permettre de chercher tous les caractères d’une chaine qui ne sont pas des voyelles minuscules. Notez que les espaces sont également des caractères et vont être trouvés ici.

Dans notre deuxième masque, on protège le métacaractère ^ avec un antislash. Notre masque va donc nous permettre de trouver toutes les voyelles de notre chaine plus le caractère « ^ ».

Dans notre troisième masque, on utilise le caractère « ^ » au milieu de la classe. Celui-ci ne possède donc pas son sens de métacaractère et nous n’avons pas besoin ici de le protéger. Ce troisième masque va nous permettre de chercher les mêmes choses que le précédent.

Notre quatrième masque utilise le métacaractère -. Dans le cas présent, il indique que notre classe de caractère contient toutes les lettres minuscules de a à z, c’est-à-dire tout l’alphabet. Notre masque va donc trouver toutes les séquences contenant une lettre de l’alphabet minuscule suivie d’un « o ».

Notez bien ici que les lettres qui ne font pas partie strictement de l’alphabet anglais commun (c’est-à-dire les lettres accentuées, les lettres avec cédilles, etc.) ne seront pas ici trouvées.

Dans notre cinquième masque, on définit deux plages ou intervalles de caractères grâce au métacaractère -. Ici, toutes les lettres de l’alphabet minuscules ou majuscules vont correspondre aux critères de la classe. Le masque va donc nous permettre de chercher toutes les séquences contenant une lettre de l’alphabet minuscule ou majuscule suivie d’un « o ».

Dans notre sixième masque, on protège cette fois-ci le caractère « – » . Notre masque va donc nous permettre de trouver les caractères « a », « – » et « z ».

Dans notre septième masque, on utilise cette fois-ci le métacaractère - pour définir une place numérique (les regex vont nous permettre de trouver n’importe quel caractère, que ce soit une lettre, un chiffre, un signe, etc.). Notre masque va donc trouver n’importe quel chiffre (de 0 à 9), la lettre « a », le lettre « z » et le caractère « – ». En effet, le caractère est ici également mentionné en fin de classe et ne possède donc pas de sens spécial et n’a pas besoin d’être protégé.

Finalement, notre dernier masque va nous permettre de trouver les caractères « / », « [ », « ] » et « \ ». Notez ici qu’il est nécessaire de protéger le caractère crochet fermant mais pas le crochet ouvrant qui sera recherché en tant que tel.

Dans cet exemple, on utilise preg_match_all() qui va renvoyer toutes les correspondances sous forme de tableau multidimensionnel. Nos masques restent pour le moment relativement simples et je sais ici que les différents tableaux renvoyés ne vont comporter qu’un seul tableau.

J’utilise donc ensuite la fonction implode() qui renvoie les différents éléments d’un tableau sous forme de chaine de caractères en les séparant avec un séparateur de notre choix. Je passe ici le séparateur virgule à cette fonction et lui passe le tableau contenu dans mes différents tableaux multidimensionnels pour qu’elle me renvoie tous les résultats.

Notez que j’aurais aussi bien pu me contenter d’utiliser print_r() comme précédemment mais comme on renvoie beaucoup de choses ce coup-ci, je voulais un rendu sous forme de chaine afin qu’il soit plus compacte et plus présentable.

 

Les classes de caractères abrégées ou prédéfinies

Le caractère d’échappement ou de protection antislash va pouvoir avoir plusieurs rôles ou plusieurs sens dans un contexte d’utilisation au sein d’expressions régulières. On a déjà vu que l’antislash nous permettait de protéger certains métacaractères, c’est-à-dire que le métacaractères ne prendra pas sa signification spéciale mais pourra être cherché en tant que caractère simple.

L’antislash va encore pouvoir être utilisé au sein de classes de caractères avec certains caractères « normaux » pour au contraire leur donner une signification spéciale.

On va ainsi pouvoir utiliser ce qu’on appelle des classes abrégées ou prédéfinies pour indiquer qu’on recherche un type de valeurs plutôt qu’une valeur ou qu’une plage de valeurs en particuliers. Les classes abrégées disponibles sont les suivantes (faites bien attention aux emplois de majuscules et de minuscules ici !) :

Classe abrégéeDescription
\wReprésente tout caractère de « mot ». Équivalent à [a-zA-Z0-9_]
\WReprésente tout caractère qui n’est pas un caractère de « mot ». Equivalent à [^a-zA- Z0-9_]
\dReprésente un chiffre. Équivalent à [0-9]
\DReprésente tout caractère qui n’est pas un chiffre. Équivalent à [^0-9]
\sReprésente un caractère blanc (espace, retour chariot ou retour à la ligne)
\SReprésente tout caractère qui n’est pas un caractère blanc
\hReprésente un espace horizontal
\HReprésente tout caractère qui n’est pas un espace horizontal
\vReprésente un espace vertical
\VReprésente tout caractère qui n’est pas un espace vertical
<!DOCTYPE html>
<html>
    <head>
        <title>Cours PHP & MySQL</title>
        <meta charset="utf-8">
        <link rel="stylesheet" href="cours.css">
    </head>
    
    <body>
        <h1>Titre principal</h1>
        <?php
            $masque1 = '/[\W]/';
            $masque2 = '/[\d]/';
            $masque3 = '/[\h]/';
            $chaine = 'Je suis Pierre, j\'ai 29 ans. Et vous ?';
            
            preg_match_all($masque1, $chaine, $tb1);
            preg_match_all($masque2, $chaine, $tb2);
            $espaces = preg_match_all($masque3, $chaine);
            echo '<pre>';
            print_r($tb1);
            echo '<br>';
            print_r($tb2);
            echo '</pre><br>';
            echo 'Ma chaine contient ' .$espaces. ' espaces horizontaux';
        ?>
        <p>Un paragraphe</p>
    </body>
</html>

 

Présentation et exemple d'utilisation des classes abrégées des regex PHP

Ici, notre premier masque nous permet de trouver tous les caractères qui n’appartiennent pas à la classe [a-ZA-Z-0-9_], c’est-à-dire tout caractère qui n’est ni une lettre de l’alphabet de base ni un chiffre ni un underscore.

Notre deuxième masque nous permet de trouver tous les caractères de type chiffres dans une chaine de caractères.

Notre troisième masque nous permet de trouver tous les espaces. Ici, on choisit d’utiliser la valeur renvoyée par défaut par preg_match_all() qui correspond au nombre de fois où le masque a été trouvé dans a chaine pour renvoyer le nombre d’espaces dans notre chaine.

Laisser un commentaire