Les Expressions Régulières

Présentation

Les expressions régulières, souvent abrégées en "regex" ou "regexp", sont un outil puissant et polyvalent pour rechercher, extraire et manipuler des chaînes de caractères à l'aide de motifs précis.

Au coeur de ces motifs se trouvent des symboles spéciaux, appelés métacaractères, qui permettent, par exemple, d'indiquer qu'un caractère peut se répéter, qu'un groupe de caractères est facultatif ou encore de définir des plages de caractères autorisés.

Vous pouvez imaginer les expressions régulières comme des outils de bricolage pour le texte. Elles vous aident à détecter et à transformer des informations en un clin d'oeil. Que ce soit pour valider une adresse e-mail, trouver des dates dans un document ou encore extraire des informations spécifiques, les regex s'avèrent être de précieuses alliées.

Création d'une Expression Régulière

Vous pouvez créer une expression régulière de deux façons. La première consiste à encadrer un motif entre deux barres obliques /. La seconde méthode utilise le constructeur de la classe RegExp, qui prend le motif sous forme de chaîne de caractères. Ces deux approches produisent le même résultat, mais la notation littérale (avec des barres obliques) est généralement plus concise et lisible.

Par exemple, pour créer une expression régulière qui recherche le mot clette dans une chaîne de caractères, vous pouvez écrire :


                    // Créer l'expression régulière en la plaçant entre deux barres obliques.
                    const regex = /clette/;
                

                    // Créer l'expression régulière en la passant en argument d'une instanciation de la classe RegExp();
                    const regex = new RegExp('clette');
                

Une fois que vous avez créé une expression régulière, vous pouvez l'utiliser pour rechercher des correspondances dans une chaîne de caractères. JavaScript propose plusieurs méthodes pour manipuler et interagir avec les expressions régulières.

Dans l'exemple suivant, nous utilisons une expression régulière contenant uniquement des caractères littéraux : clette. Cela signifie que l'expression cherche exactement cette séquence de caractères, sans interprétation particulière.

La chaîne de caractères à analyser est stockée dans la constante texte. Pour vérifier si cette chaîne contient le mot clette, nous utilisons la méthode test(). Cette méthode, appliquée sur l'expression régulière, renvoie true si une correspondance est trouvée, et false sinon :


                    const regex = /clette/;
                    const texte = 'Quelle clette ce pey !';
                    const correspondance = regex.test(texte); // Renvoie true
                

Les expressions régulières ne se limitent pas aux simples recherches de mots. Grâce à des éléments avancés comme les métacaractères, les quantificateurs et les modificateurs, il est possible de construire des motifs bien plus complexes et précis. Ces outils permettent, par exemple, de rechercher des variantes d'un mot, de détecter un modèle répétitif ou d'ignorer la casse des lettres.

Les Classes de Caractères

Les classes de caractères permettent de spécifier un ensemble de caractères possibles à un emplacement donné dans une chaîne de caractères. Elles sont particulièrement utiles pour rechercher plusieurs variations d'un même motif en une seule expression régulière.

Les classes de caractères énumérées

Les classes de caractères énumérées vous permettent de définir exactement quels caractères vous recherchez. On les écrit entre crochets [] et on y liste les caractères autorisés.

  • [abc] : Lorsque des caractères littéraux sont placés entre crochets, la recherche portera sur n'importe quel caractère qui est dans l'ensemble spécifié. Par exemple, cette classe trouvera une correspondance dans la chaîne de caractères à tester si celle-ci contient au moins l'un des caractères suivant : a, b ou c.
    
                                /* Exemple AVEC correspondance */
    
                                const regex = /[abc]/;
                                const texte = "Il observe les étoiles.";
    
                                // Correspondance trouvée car "b" est présent dans la chaîne de caractère à tester.
                                console.log(regex.test(texte)); // Affiche : true
                            
    
                                /* Exemple SANS correspondance */
    
                                const regex = /[abc]/;
                                const texte = "Il est d'humeur morose.";
    
                                // Correspondance non trouvée car ni "a", ni "b", ni "c" ne sont présents dans la chaîne de caractère à tester.
                                console.log(regex.test(texte)); // Affiche : false
                            
  • [^abc] : Lorsque le caractère ^ est placé immédiatement après l'ouverture du crochet, il signifie une négation. C'est-à-dire que la recherche portera sur n'importe quel caractère qui n'est pas dans l'ensemble spécifié. Par exemple, cette classe trouvera une correspondance si la chaîne de caractères à tester contient au moins un caractère autre que a, b ou c.
    
                                /* Exemple AVEC correspondance */
    
                                const regex = /[^abc]/;
                                const texte = "arctic monkeys";
    
                                // Correspondance trouvée car la chaîne contient d'autres caractères que "a", "b" ou "c".
                                console.log(regex.test(texte)); // Affiche : true
                            
    
                                /* Exemple SANS correspondance */
    
                                const regex = /[^abc]/;
                                const texte = "abba";
    
                                // Correspondance non trouvée car la chaîne ne contient que les caractères "a" et "b".
                                console.log(regex.test(texte)); // Affiche : false
                            

Les classes de caractères avec plage

Les classes de caractères avec plage vous permettent de sélectionner une série de caractères qui se suivent, sans avoir à les écrire un par un. Elles s'écrivent entre crochets [] et vous indiquez le début et la fin de la plage en les séparant par un tiret -.

  • [0-9] : Une plage de caractères peut être spécifiée en utilisant un tiret -. La recherche portera sur n'importe quel chiffre entre 0 et 9 (inclus).
    
                                /* Exemple AVEC correspondance */
    
                                const regex = /[0-9]/;
                                const texte = "Louis a obtenu 2 sur 10!";
    
                                // Correspondance trouvée car la chaîne contient au moins un caractère numérique.
                                console.log(regex.test(texte)); // Affiche : true
                            
    
                                /* Exemple SANS correspondance */
    
                                const regex = /[0-9]/;
                                const texte = "Louis a obtenu deux sur dix!";
    
                                // Correspondance non trouvée car la chaîne ne contient aucun caractère numérique.
                                console.log(regex.test(texte)); // Affiche : false
                            
  • [a-z] : Correspond à n'importe quelle lettre minuscule de l'alphabet (de a à z).
    
                                /* Exemple AVEC correspondance */
    
                                const regex = /[a-z]/;
                                const texte = "Le chargé de cours en JS semble être un noob avec les Regex!";
    
                                // Correspondance trouvée car la chaîne contient des lettres minuscules.
                                console.log(regex.test(texte)); // Affiche : true
                            
    
                                /* Exemple SANS correspondance */
    
                                const regex = /[a-z]/;
                                const texte = "SAPERLIPOPETTE!";
    
                                // Correspondance non trouvée car la chaîne ne contient aucune lettre minuscule.
                                console.log(regex.test(texte)); // Affiche : false
                            

Notez qu'il est possible de combiner plusieurs plages de caractères. Par exemple, si l'on souhaite rechercher toutes les lettres, qu'elles soient minuscules ou majuscules, on peut utiliser la plage suivante : [a-zA-Z].

Les classes de caractères abrégées

Les classes de caractères abrégées sont des raccourcis permettant de représenter des groupes de caractères courants sans avoir à les écrire entièrement. Elles commencent par une barre oblique inversée \ suivie d'une lettre spécifique.

  • \d (équivalent à [0-9]) : Correspond à n'importe quel chiffre entre 0 et 9 (inclus).
  • \w (équivalent à [A-Za-z0-9_]) : Correspond à n'importe quel caractère alphanumérique, c'est-à-dire une lettre, un chiffre ou un trait d'union.
  • \s : Correspond à n'importe quel espace blanc, c'est à dire un espace, une tabulation, un saut de ligne ou un retour chariot.

Il existe une version inversée des classes de caractères abrégées, c'est-à-dire qu'elle recherche tous les caractères excepté ceux spécifiés par la classe abrégée. Pour déclarer une classe abrégée inversée, il suffit d'utiliser la même lettre en majuscule.

  • \D (équivalent à [^0-9]) : correspond à tout caractère excepté les chiffres.
  • \W (équivalent à [^A-Za-z0-9_]) : correspond à tout caractère excepté les caractères alphanumérique, c'est à dire une lettre, un chiffre ou un trait d'union.
  • \S correspond à tout caractère excepté les espaces blancs (espaces, tabulations, sauts de ligne et retours chariot).

Les Caractères Spéciaux

Les caractères spéciaux, en matière d'expressions régulières, sont des caractères qui ont un sens particulier et ne sont pas interprétés littéralement. Ils sont utilisés pour définir des motifs plus complexes et précis :

  • . : Correspond à n'importe quel caractère, sauf un caractère de saut de ligne.
    
                                // Motif débutant par "ab",
                                // suivi d'un caractère de n'importe quel type (excépté les sauts de ligne),
                                // suivi par le caractère "d".
                                const regex = /ab.d/;
    
                                // Correspondance trouvée : "abcd".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : true
    
                                // Correspondance trouvée : "ab2d".
                                console.log(regex.test("Bruno récite l'alphabet : ab2def")); // Affiche : true
    
                                // Correspondance trouvée : "ab d".
                                console.log(regex.test("Bruno récite l'alphabet : ab def")); // Affiche : true
    
                                // Correspondance trouvée : "ab!d".
                                console.log(regex.test("Bruno récite l'alphabet : ab!def")); // Affiche : true
    
                                // Correspondance non trouvée car il y a plus d'une caractère entre "ab" et "d".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : false
    
                                // Correspondance non trouvée car il n'y a aucun caractère entre "ab" et "d".
                                console.log(regex.test("Bruno récite l'alphabet : abdef")); // Affiche : false
    
                                // Correspondance non trouvée car il y a un retour à la ligne entre "ab" et "d".
                                console.log(regex.test("Bruno récite l'alphabet : ab\ndef")); // Affiche : false
                            
  • | : Utilisé pour définir des alternatives (fonctionne comme l'opérateur "OU").
    
                                // Motif débutant par "ab",
                                // suivi du caractère "c" ou du caractère "d".
                                const regex = /abc|d/;
    
                                // Correspondance trouvée : "abc".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : true
    
                                // Correspondance trouvée : "abd".
                                console.log(regex.test("Bruno récite l'alphabet : abdef")); // Affiche : true
    
                                // Correspondance non trouvée car ni le caractère "c" ni le caractère "d" n'est présent après les caractères "ab".
                                console.log(regex.test("Bruno récite l'alphabet : abef")); // Affiche : false
                            

Les Quantificateurs

Les quantificateurs sont des métacaractères spéciaux dans les expressions régulières qui vous permettent de spécifier combien de fois un élément précédent doit se produire.

  • * : Correspond à 0 ou plusieurs occurrences de l'expression précédente.
    
                                // Motif débutant par "ab",
                                // suivi par 0 ou plusieurs "c",
                                // suivi par le caractère "d".
                                const regex = /abc*d/;
    
                                // Correspondance trouvée : "abd".
                                console.log(regex.test("Bruno récite l'alphabet : abdef")); // Affiche : true
    
                                // Correspondance trouvée : "abcd".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : true
    
                                // Correspondance trouvée : "abccd".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il manque le "d" après le "b".
                                console.log(regex.test("Bruno récite l'alphabet : abef")); // Affiche : false
    
                                // Correspondance non trouvée : Il manque le "d" après le "c".
                                console.log(regex.test("Bruno récite l'alphabet : abcef")); // Affiche : false
                            
  • + : Correspond à 1 ou plusieurs occurrences de l'expression précédente.
    
                                // Motif débutant par "ab",
                                // suivi par 1 ou plusieurs "c",
                                // suivi par le caractère "d".
                                const regex = /abc+d/;
    
                                // Correspondance trouvée : "abcd".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : true
    
                                // Correspondance trouvée : "abccd".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il manque au moins 1 "c" entre le "b" et le "d".
                                console.log(regex.test("Bruno récite l'alphabet : abdef")); // Affiche : false
                            
  • ? : Correspond à 0 ou 1 occurrence de l'expression précédente.
    
                                // Motif débutant par "ab",
                                // suivi par 0 ou 1 "c",
                                // suivi par le caractère "d".
                                const regex = /abc?d/;
    
                                // Correspondance trouvée : "abd".
                                console.log(regex.test("Bruno récite l'alphabet : abdef")); // Affiche : true
    
                                // Correspondance trouvée : "abcd".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il ne peut y avoir qu'un seul "c" au maximum entre le "b" et le "d".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : false
                            
  • {n} : Correspond à exactement n occurrences de l'élément précédent.
    
                                // Motif débutant par "ab",
                                // suivi par précisément 3 "c",
                                // suivi par le caractère "d".
                                const regex = /abc{3}d/;
    
                                // Correspondance trouvée : "abcccd".
                                console.log(regex.test("Bruno récite l'alphabet : abcccdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il doit y avoir précisément 3 "c" entre le "b" et le "d".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : false
                            
  • {n,} : Correspond à au moins n occurrences de l'élément précédent.
    
                                // Motif débutant par "ab",
                                // suivi par au moins 2 "c",
                                // suivi par le caractère "d".
                                const regex = /abc{2,}d/;
    
                                // Correspondance trouvée : "abccd".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : true
    
                                // Correspondance trouvée : "abcccd".
                                console.log(regex.test("Bruno récite l'alphabet : abcccdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il doit y avoir au moins 2 "c" entre le "b" et le "d".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : false
                            
  • {n,m} : Correspond à entre n et m occurrences de l'élément précédent.
    
                                // Motif débutant par "ab",
                                // suivi par, entre 2 et 4 "c",
                                // suivi par le caractère "d".
                                const regex = /abc{2,4}d/;
    
                                // Correspondance trouvée : "abccd".
                                console.log(regex.test("Bruno récite l'alphabet : abccdef")); // Affiche : true
    
                                // Correspondance trouvée : "abcccd".
                                console.log(regex.test("Bruno récite l'alphabet : abcccdef")); // Affiche : true
    
                                // Correspondance trouvée : "abccccd".
                                console.log(regex.test("Bruno récite l'alphabet : abccccdef")); // Affiche : true
    
                                // Correspondance non trouvée : Il doit y avoir entre 2 et 4 "c" entre le "b" et le "d".
                                console.log(regex.test("Bruno récite l'alphabet : abcdef")); // Affiche : false
                                console.log(regex.test("Bruno récite l'alphabet : abcccccdef")); // Affiche : false
                            

Les quantificateurs non gourmands

Les quantificateurs non gourmands permettent de limiter la capture d'une expression régulière au strict minimum nécessaire. Cela est particulièrement utile lorsque vous travaillez avec des formats structurés comme le HTML ou le JSON, car cela vous aide à extraire uniquement la portion de texte souhaitée.

Par défaut, les quantificateurs gourmands capturent autant de texte que possible. Par exemple, pour extraire le contenu textuel d'un paragraphe en HTML avec le motif /<p>.*<\/p>/, le quantificateur gourmand va capturer tout le texte depuis la première balise d'ouverture <p> jusqu'à la dernière balise de fermeture </p> de la chaîne à analyser.

Pour l'exemple suivant, nous allons utiliser la méthode match(), qui permet d'extraire les correspondances trouvées par une expression régulière dans une chaîne de caractères. Contrairement à test(), qui renvoie simplement true ou false selon qu'une correspondance est trouvée ou non, match() retourne un tableau contenant la ou les parties du texte correspondant au motif recherché.


                    /* Exemple avec quantificateur gourmand */

                    // Motif débutant par l'ouverture de la balise <p>,
                    // suivi 0 ou plusieurs occurrences de n'importe quel caractère,
                    // suivi de la fermeture de balise </p>.
                    const regex = /<p>.*<\/p>/;

                    // Code HTML à analyser.
                    const codeHTML = "<div><p>Premier paragraphe</p><p>Deuxième paragraphe</p></div>";

                    // La regex capture tout entre le premier <p> et le dernier </p>.
                    console.log(codeHTML.match(regex)); // Affiche : Array ["<p>Premier paragraphe</p><p>Deuxième paragraphe</p>"]
                

Pour rendre ce quantificateur non gourmand, il suffit d'ajouter un point d'interrogation ? juste après le quantificateur. Ainsi, *?, +?, ??, {n,}? et {n,m}? capturent le minimum d'occurrences possible, ce qui évite de prendre plus de texte que nécessaire.


                    /* Exemple avec quantificateur non gourmand */

                    // Motif débutant par l'ouverture de la balise <p>,
                    // suivi 0 ou plusieurs occurrences de n'importe quel caractère (le minimum),
                    // suivi de la fermeture de balise </p>.
                    const regex = /<p>.*?<\/p>/;

                    // Code HTML à analyser.
                    const codeHTML = "<div><p>Premier paragraphe</p><p>Deuxième paragraphe</p></div>";

                    // La regex capture uniquement le premier <p> rencontré.
                    console.log(codeHTML.match(regex)); // Affiche : Array ["<p>Premier paragraphe</p>"]
                

Les Métacaractères de Position

Les métacaractères de position sont des éléments spéciaux dans les expressions régulières qui correspondent à des positions particulières dans une chaîne de caractères, plutôt qu'à des caractères spécifiques :

  • ^ : Utilisé en tant que premier caractère, il correspond au début de la chaîne.
    
                                // La chaîne doit commencer par le motif "abc".
                                const regex = /^abc/;
    
                                // Correspondance trouvée : "abc".
                                console.log(regex.test("abcdef sont les 6 premières lettres de l'alphabet!")); // Affiche : true
    
                                // Correspondance non trouvée car la chaîne de caractère ne commence pas par "abc".
                                console.log(regex.test("Bruno récite l'alphabet : abc")); // Affiche : false
                            
  • $ : Utilisé en tant que dernier caractère, il correspond à la fin de la chaîne.
    
                                // La chaîne doit terminer par le motif "abc".
                                const regex = /abc$/;
    
                                // Correspondance trouvée : "abc".
                                console.log(regex.test("Bruno récite l'alphabet : abc")); // Affiche : true
    
                                // Correspondance non trouvée car la chaîne de caractère ne termine pas par "abc".
                                console.log(regex.test("abcdef sont les 6 premières lettres de l'alphabet!")); // Affiche : false
                            
  • \b : Ce métacaractère correspond à la position d'une limite de mot, c'est-à-dire la position où un caractère d'un mot n'est pas suivi ou précédé d'un autre caractère de mot.
    • Dans l'exemple suivant, la regex /\bport/ recherche les séquence qui commencent par port :
      
                                          // La regex recherche les mots qui commencent par "port".
                                          const regex = /\bport/;
      
                                          // Correspondance trouvée : "port" est au début du mot "portail".
                                          console.log(regex.test("Ce portail est magnifique")); // Affiche : true
      
                                          // Correspondance non trouvée car aucun mot ne commence par "port" dans cette phrase.
                                          console.log(regex.test("Je ne vois pas le rapport")); // Affiche : false
                                      
    • Dans l'exemple suivant, la regex /port\b/ recherche les séquence qui finissent par port :
      
                                          // La regex recherche les mots qui se terminent par "port".
                                          const regex = /port\b/;
      
                                          // Correspondance trouvée : "port" se trouve à la fin du mot "rapport".
                                          console.log(regex.test("Je ne vois pas le rapport")); // Affiche : true
      
                                          // Correspondance non trouvée car aucun mot ne se termine par "port" ici.
                                          console.log(regex.test("Ce portail est magnifique")); // Affiche : false
                                      
    • Dans l'exemple suivant, la regex /\bsoleil\b/ recherche les séquence soleil en tant que mot entier, c'est-à-dire n'étant pas attaché à d'autres caractères alphanumériques.
      
                                          // La regex recherche le mot "soleil" comme mot complet.
                                          const regex = /\bsoleil\b/;
      
                                          // Correspondance trouvée : "soleil" est un mot isolé.
                                          console.log(regex.test("Le soleil est éblouissant!")); // Affiche : true
      
                                          // Correspondance non trouvée car "soleil" est intégré dans "ensoleillé".
                                          console.log(regex.test("Le temps est ensoleillé!")); // Affiche : false
                                      
  • \B : Ce métacaractère correspond à la position qui n'est pas une limite de mot. En d'autres termes, il correspond à des positions à l'intérieur des mots.
    • Dans l'exemple suivant, la regex /\Bport/ recherche les séquences port uniquement lorsqu'elles ne sont pas en début de mot :
      
                                          // La regex recherche "port" uniquement s'il est précédé par un caractère alphanumérique.
                                          const regex = /\Bport/;
      
                                          // Correspondance trouvée : "port" est à l'intérieur du mot "rapport".
                                          console.log(regex.test("Je ne vois pas le rapport")); // Affiche : true
      
                                          // Correspondance non trouvée car dans "portail", "port" est au début du mot.
                                          console.log(regex.test("Ce portail est magnifique")); // Affiche : false
                                      
    • Dans l'exemple suivant, la regex /port\B/ recherche les séquences port uniquement lorsqu'elles ne sont en fin de mot :
      
                                          // La regex recherche "port" uniquement s'il est suivi par un caractère alphanumérique.
                                          const regex = /port\B/;
      
                                          // Correspondance trouvée : "port" est au début du mot "portail".
                                          console.log(regex.test("Ce portail est magnifique")); // Affiche : true
      
                                          // Correspondance non trouvée car "port" est à la fin du mot "rapport".
                                          console.log(regex.test("Je ne vois pas le rapport")); // Affiche : false
                                      
    • Dans l'exemple suivant, la regex /\Bsoleil\B/ recherche les séquences soleil uniquement lorsqu'elles sont inclues dans un autre mot :
      
                                          // La regex recherche "soleil" uniquement lorsqu'il fait partie d'un mot.
                                          const regex = /\Bsoleil\B/;
      
                                          // Correspondance trouvée : "soleil" est intégré dans "ensoleillé".
                                          console.log(regex.test("Le temps est ensoleillé!")); // Affiche : true
      
                                          // Correspondance non trouvée car "soleil" est isolé dans cette phrase.
                                          console.log(regex.test("Le soleil est éblouissant!")); // Affiche : false
                                      

Échapper les caractères

Pour pouvoir utiliser des caractères dédiés à la création de motifs en tant que caractères littéraux, il suffira d'utiliser le caractère d'échappement habituel : \.

Dans l'exemple suivant, nous souhaitons vérifier la présence du symbole + dans une chaîne de caractères. Cependant, en expressions régulières, ce symbole est un métacaractère utilisé pour indiquer qu'un élément doit apparaître au moins une fois. Pour rechercher + comme un simple caractère et non comme un motif, il faut l'échapper en le précédant d'une barre oblique inversée \ dans la regex :


                    // La regex recherche la présence de plus "+".
                    const regex = /\+/;

                    // Correspondance trouvée : "+".
                    console.log(regex.test("7+10")); // Affiche : true

                    // Correspondance non trouvée car aucun "+" n'est présent dans la chaîne.
                    console.log(regex.test("10-7")); // Affiche : false
                

Les Groupes et Captures

Les groupes permettent de définir des blocs logiques pour, par exemple, appliquer un quantificateur à un ensemble complet d'éléments ou gérer plusieurs alternatives au sein d'un même motif. Cette structure rend l'expression plus claire et facilite la correspondance d'éléments qui partagent une partie commune.


                    // Recherche soit le mot "Candyman" soit le mot "Beetlejuice" présent au moins.
                    const regex = /(Candyman|Beetlejuice)+/;

                    // Ces tests retournent "true" car chacun d'eux contient au moins une correspondance du mot "Candyman" et/ou "Beetlejuice" :
                    console.log(regex.test("Beetlejuice est un film culte de Tim Burton sorti en 1988.")); // Affiche : true
                    console.log(regex.test("Beetlejuice Beetlejuice Beetlejuice.")); // Affiche : true
                    console.log(regex.test("Candyman est un film d'horreur inspiré d'une légende urbaine.")); // Affiche : true
                    console.log(regex.test("Beetlejuice et Candyman sont deux films d'horreur.")); // Affiche : true

                    // Ce test retourne "false" car aucun des deux mots ("Candyman" et "Beetlejuice") n'est présent dans la chaîne.
                    console.log(regex.test("Heretic est un film d'horreur américain de 2024.")); // Affiche : false
                

Les Groupes Capturants

Les groupes capturants permettent d'extraire des parties spécifiques d'une chaîne de caractères. Pour capturer une correspondance, il suffit d'entourer le motif recherché avec des parenthèses ().

Par exemple, si nous travaillons avec une chaîne contenant un prénom et un nom et que nous souhaitons les récupérer séparément :


                    // Capturer deux séquences alphanumériques séparées par un espace.
                    const regex = /(\w+) (\w+)/;
                    const chaine = "Focan Claudy";

                    const resultat = chaine.match(regex);
                    console.log(resultat);
                    /*
                        Affiche : 
                            Array(3) [ "Focan Claudy", "Focan", "Claudy" ]
                                0: "Focan Claudy"   [correspondance complète]
                                1: "Focan"          [premier groupe : $1]
                                2: "Claudy"         [deuxième groupe : $2]
                    */
                

Les groupes capturants offrent de nombreuses possibilités. Par exemple, nous pouvons automatiser l'inversion du prénom et du nom en utilisant la fonction replace(). Cette fonction permet d'identifier des correspondances à l'aide d'un motif et de les remplacer par une nouvelle structure.


                    // Capturer deux séquences alphanumériques séparées par un espace.
                    const regex = /(\w+) (\w+)/;
                    const chaine = "Focan Claudy";

                    const resultat = chaine.replace(regex, "$2 $1");
                    console.log(resultat); // Affiche : Claudy Focan
                

Les Groupes non Capturants

À côté des groupes capturants, il existe des groupes non capturants qui permettent de regrouper certaines parties d'une expression régulière sans en faire des captures. Autrement dit, ils servent uniquement à organiser ou à appliquer des quantificateurs à un ensemble d'éléments, sans influencer le résultat des captures. Pour cela, on utilise la syntaxe (?:...) au lieu de simples parenthèses.

Imaginons que nous souhaitions identifier une suite de chiffres précédée soit du préfixe national 0, soit de l'indicatif international belge +32. Plutôt que de capturer ce préfixe comme un élément distinct, nous allons l'inclure dans un groupe non capturant afin de ne conserver en capture que la séquence de chiffres. Cela permet d'uniformiser le format du numéro, quel que soit le mode de saisie de l'utilisateur :


                // La séquence contient deux groupes et sera prise en compte lors de la recherche d'occurrences,
                // mais si une correspondance est trouvée, seul le second groupe sera effectivement capturé.
                const regex = /(?:\+32|0){1}(\d{9})/;

                // (?:\+32|0) : "+32" n'est pas capturée.
                // (\d{9}) : "123456789" est capturé.
                const resultat = "+32123456789".match(regex);
                console.log(resultat);
                /*
                    Affiche : 
                        Array(2) [ "+32123456789", "123456789" ]
                          0: "+32123456789"   [correspondance complète]
                          1: "123456789"       [premier groupe : $1]
                */

                // (?:\+32|0) : "0" n'est pas capturée.
                // (\d{9}) : "123456789" est capturé.
                const resultat = "0123456789".match(regex);
                console.log(resultat);
                /*
                    Affiche : 
                        Array(2) [ "0123456789", "123456789" ]
                          0: "0123456789"   [correspondance complète]
                          1: "123456789"       [premier groupe : $1]
                */
                

Les Assertions Conditionnelles

Les assertions conditionnelles représentent des conditions spécifiques que nous pouvons imposer lors de la recherche de motifs au sein de chaînes de caractères. Ces outils constituent un moyen d'affiner nos recherches, en nous permettant d'extraire précisément les données dont nous avons besoin. Les assertions offrent la capacité de vérifier si un motif donné est présent ou non, soit avant, soit après un autre motif au sein d'une chaîne de caractères.

Une caractéristique essentielle des assertions est qu'elles ne captent pas le motif de l'assertion en cas de correspondance. Autrement dit, le motif de l'assertion n'est pas inclus dans les résultats des correspondances, ce qui permet de maintenir la précision des données extraites.

Il existe deux types principaux d'assertions, les assertions positives et les assertions négatives :

  • Les assertions positives : Permettent de rechercher un motif donné tout en exigeant qu'il soit suivi par un autre motif particulier. Par exemple, vous pourriez chercher des mots qui sont suivis par le mot "px" dans un texte.
  • Les assertions négatives : Permettent de rechercher un motif spécifique tout en exigeant qu'il ne soit pas suivi par un autre motif particulier. Cela peut être utile lorsque vous devez exclure des correspondances basées sur des conditions spécifiques.

Les assertions positives (positive Lookahead et positive lookbehind)

Une assertion positive est un moyen de rechercher un motif spécifique dans une chaîne de caractères tout en exigeant que ce motif soit précédé ou suivi d'un autre motif particulier, sans inclure ce dernier dans le résultat.

  • La lookahead positive permet de vérifier si un motif est situé avant un autre motif :
    • Positive lookahead X(?=Y) :
      • X est le motif que nous recherchons.
      • Y le motif qui doit nécessairement suivre le motif recherché.
      • Dans l'exemple suivant, nous désirons trouver les valeurs numériques qui sont précédées de px :

        
                                                // Valeurs numériques (\d) d'au moins un caractère (+) qui sont précédées du mot "px" (?=px).
                                                // Ne pas s'arrêter à la première capture (g).
                                                const regex = /\d+(?=px)/g;
                                                const texte = "42 rectangle de 12px de longueur et 8px de largeur.";
                                                console.log(texte.match(regex));
                                                /*
                                                    Affiche :
                                                        Array [ "12", "8" ]
                                                            0: "12"
                                                            1: "8"
                                                            length: 2
                                                */
                                            
  • La lookbehind positive permet de vérifier si un motif est situé après un autre motif :
    • Positive lookbehind (?<=Y)X :
      • X est le motif que nous recherchons.
      • Y le motif qui doit nécessairement précéder le motif recherché.
      • Dans l'exemple suivant, nous désirons trouver les valeurs numériques précédées de $ :

        
                                            // Valeurs numériques (\d) d'au moins un caractère (+) qui sont précédées du signe dollar "$" (?<=$).
                                            // Ne pas s'arrêter à la première capture (g).
                                            const regex = /(?<=\$)\d+/g;
                                            const texte = "La semaine, le prix est de $42 alors que le week-end, il est de $33. Un delta de 9 qui ne s'explique pas !";
                                            console.log(texte.match(regex));
                                            /*
                                                Affiche :
                                                    Array [ "42", "33" ]
                                                        0: "42"
                                                        1: "33"
                                                        length: 2
                                            */
                                        

Les assertions négatives (negative Lookahead et negative lookbehind)

Une assertion négative est un moyen de rechercher un motif spécifique dans une chaîne de caractères tout en exigeant que ce motif ne soit pas suivi par un autre motif particulier :

  • La lookahead Negative permet de vérifier si un motif n'est situé avant un autre motif :
    • Negative lookahead X(?!Y) :
      • X est le motif que nous recherchons.
      • Y le motif qui doit nécessairement ne pas suivre le motif recherché.
  • La lookbehind Negative permet de vérifier si un motif n'est situé après un autre motif :
    • Negative lookbehind (?<!Y)X :
      • X est le motif que nous recherchons.
      • Y le motif qui doit nécessairement ne pas précéder le motif recherché.

Recherche non linéaire des motifs

Dans certains cas, on souhaite vérifier la présence de plusieurs séquences au sein d'une chaîne de caractères sans imposer un ordre spécifique entre elles.

Par exemple, cela s'applique aux mots de passe, où il est souvent nécessaire, pour des raisons de sécurité, d'inclure différents types de caractères tels que des lettres majuscules et minuscules, des chiffres et des caractères spéciaux, sans que leur ordre soit spécifié.

Les assertions anticipées sont particulièrement pratiques dans ce contexte car elles analysent la chaîne de caractères successivement, permettant ainsi de valider des motifs indépendamment de leur ordre d'apparition.

Il est à préciser que les assertions anticipées, en raison de leur nature non-capturante, ne capturent pas le texte correspondant au motif trouvé même en cas de réussite. Ainsi, si vous souhaitez obtenir le résultat de la recherche, vous devrez ajouter un motif de synthèse capturant immédiatement après. Ce motif capturant permettra alors de récupérer le texte associé à la réussite des assertions.

Voici un exemple illustrant la validation d'un mot de passe, s'assurant qu'il contient au moins 8 caractères et qu'il comprend au moins un caractère de chacune des catégories suivantes : lettre minuscule, lettre majuscule, chiffre et caractère spécial :


                    const regex = /^(?=.*[a-z]+)(?=.*[A-Z]+)(?=.*\d+)(?=.*[@$!%*?&]+)[A-Za-z\d@$!%*?&]{8,}$/;

                    // Correspondance trouvée : "!gRa7jJ@".
                    console.log(regex.test("!gRa7jJ@")); // Affiche : 1

                    // Correspondance non trouvée car le mot de passe contient moins de 8 caractères.
                    console.log(regex.test("8sR!")); // Affiche : 0

                    // Correspondance non trouvée car le mot de passe ne contient ni lettres minuscules, 
                    // ni lettres majuscules, ni caractères spéciaux.
                    console.log(regex.test("12345678")); // Affiche : 0

                    // Correspondance non trouvée car le mot de passe ne contient pas de caractères spéciaux.
                    console.log(regex.test("abcd5EFG")); // Affiche : 0
                

Les Modificateurs aussi appelés Drapeaux (flags)

Les modificateur sont utilisés avec les expressions régulières pour changer leur comportement lors de la recherche de correspondances dans une chaîne de caractères :

  • Le modificateur i (insensible à la casse) : Lorsque ce modificateur est utilisé, la recherche de correspondances est insensible à la casse, ce qui signifie qu'elle correspond à des lettres majuscules et minuscules :
    
                                // Sans le modificateur "i" :
                                const regex = /clette/;
                                const texte = 'Quelle Clette ce pey !';
                                const resultat = regex.test(texte); // Renvoie false
                            
    
                                // Avec le modificateur "i" 
                                const regex = /clette/i;
                                // Ou avec la classe RegEx() : const regex = new RegExp('clette', 'i');
                                const texte = 'Quelle Clette ce pey !';
                                const resultat = regex.test(texte); // Renvoie true
                            
  • Le modificateur g (global) : Ce modificateur est utilisé pour rechercher toutes les correspondances dans la chaîne, pas seulement la première :
    
                                // Sans le modificateur "g" :
                                const regex = /clette|pey/;
                                const texte = 'Quelle clette ce pey !';
    
                                // Match est une méthode permettant de récupérer dans un tableau la ou les correspondance(s) respectant le motif de l'expression régulière.
                                const resultat = texte.match(regex); // Renvoie ["clette"]
                            
    
                                // Avec le modificateur "g" :
                                const regex = /clette|pey/g;
                                const texte = 'Quelle clette ce pey !';
    
                                // Match est une méthode permettant de récupérer dans un tableau la ou les correspondance(s) respectant le motif de l'expression régulière.
                                const resultat = texte.match(regex); // Renvoie ["clette", "pey"]
                            
  • Le modificateur m (multi-lignes) : Ce modificateur est utile lorsque vous avez besoin d'utiliser les métacaractères de position "^" et "$" ligne par ligne et non plus sur le début et la fin de la chaîne entière :
    
                                // Sans le modificateur "m" :
                                // Le regex suivant correspond si la chaîne de caractères commence (^) par le mot "Ligne" suivi d'un espace et ensuite d'un chiffre (\d).
                                const regex = /^Ligne \d/;
                                const texte = "Lorem Ipsum!\nLigne 2 Lorem Ipsum!\nLigne 3 Lorem Ipsum !";
    
                                // Match est une méthode permettant de récupérer dans un tableau la ou les correspondance(s) respectant le motif de l'expression régulière.
                                const resultat = texte.match(regex); // Renvoie null
                            
    
                                // Avec le modificateur "m" :
                                // Le regex suivant correspond si une ligne commence (^) par le mot "Ligne" suivi d'un espace et ensuite d'un chiffre (\d).
                                const regex = /^Ligne \d/m;
                                const texte = "Lorem Ipsum!\nLigne 2 Lorem Ipsum!\nLigne 3 Lorem Ipsum !";
    
                                // Match est une méthode permettant de récupérer dans un tableau la ou les correspondance(s) respectant le motif de l'expression régulière.
                                const resultat = texte.match(regex); // Renvoie ["Ligne 2"]
                            

    Il est aussi possible de combiner plusieurs modificateurs :

    
                                // Avec les modificateur "g" et "m" :
                                // Le regex suivant correspond pour chaque ligne commençant (^) par le mot "Ligne" suivi d'un espace et ensuite d'un chiffre (\d).
                                const regex = /^Ligne \d/gm;
                                const texte = "Lorem Ipsum!\nLigne 2 Lorem Ipsum!\nLigne 3 Lorem Ipsum !";
    
                                // Match est une méthode permettant de récupérer dans un tableau la ou les correspondance(s) respectant le motif de l'expression régulière.
                                const resultat = texte.match(regex); // Renvoie ["Ligne 2", "Ligne 3"]
                            

Les modificateurs que nous venons de voir sont les plus courament utilisés mais si vous désirez en savoir plus sur le sujet, rendez-vous sur la documentation MDN Web Docs.

Méthodes de Manipulation

il existe plusieurs méthodes pour manipuler des expressions régulières. Ces méthodes sont couramment utilisées pour effectuer des opérations de recherche, de remplacement et de correspondance dans des chaînes de caractères.

  • test() : Utilisée pour vérifier si une expression régulière correspond à une partie d'une chaîne de caractères. Elle renvoie "true" si une correspondance est trouvée, sinon elle renvoie "false" :
    
                                const texte = "Claudy Focan aime la photographie.";
                                const regex = /la/;
                                const resultat = regex.test(texte); // Renvoie true
                            
  • exec() : Utilisée pour récupérer des informations sur la première correspondance trouvée dans une chaîne de caractères. Elle renvoie un objet générique contenant les détails de la correspondance :
    
                                const texte = "Claudy Focan aime la photographie.";
                                const regex = /la/;
                                const resultat = regex.exec(texte);
                                console.log(resultat);
                                /*
                                    Affiche : 
                                        Array [ "la" ]
                                            0: "la"
                                            groups: undefined
                                            index: 1
                                            input: "Claudy Focan aime la photographie."
                                            length: 1
                                */
                            
  • match() : Utilisée pour récupérer un tableau de toutes les correspondances trouvées dans une chaîne de caractères en utilisant une expression régulière. Pour obtenir toutes les correspondances, il est nécessaire d'utiliser le marqueur "g" du groupe de capture dans le regex. Si le marqueur "g" n'est pas utilisé, la méthode se comportera de la même manière qu'un exec() :
    
                                const texte = "Claudy Focan aime la photographie.";
                                const regex = /la/g;
                                const resultat = texte.match(regex);
                                console.log(resultat);
                                /*
                                    Affiche : 
                                        Array [ "la", "la" ]
                                            0: "la"
                                            1: "la"
                                            length: 2
                                */
                            
  • replace() : Utilisée pour rechercher et remplacer des correspondances dans une chaîne de caractères par une nouvelle chaîne ou une fonction :
    
                                const texte = "Claudy Focan aime la photographie.";
                                const regex = /la/;
                                const resultat = texte.replace(regex, "");
                                console.log(resultat); // Affiche : Cudy Focan aime  photographie.
                            

Il existe de nombreuses autres méthodes pour manipuler les expressions régulières. Si vous désirez en savoir plus sur le sujet, rendez-vous sur la documentation MDN Web Docs.

Exercices

  1. Exo-les-expressions-regulieres-1 :
    • Objectif : Réaliser une expression régulière permettant de vérifier si une chaîne de caractères est une couleur hexadécimal (sans alpha).
    • Format d'une couleur hexadécimal :
      • Composée soit de 4 caractères soit de 7.
      • Commence toujours par un "#".
      • Les caractères suivants peuvent être des chiffres ou des lettres (minuscules ou majuscules) allant de "a" à "f".
    • Chaînes à tester :
      
                                          // Remplacez "null" par votre expression régulière.
                                          const regexExo1 = null;
      
                                          console.log(regexExo1.test('#123456')); // Affiche : true
                                          console.log(regexExo1.test('#4242FF')); // Affiche : true
                                          console.log(regexExo1.test('#4242ff')); // Affiche : true
                                          console.log(regexExo1.test('#F90')); // Affiche : true
                                          console.log(regexExo1.test('#12345')); // Affiche : false
                                          console.log(regexExo1.test('#1234567')); // Affiche : false
                                          console.log(regexExo1.test('#4F4G42')); // Affiche : false
                                          console.log(regexExo1.test('#afé465')); // Affiche : false
                                          console.log(regexExo1.test('#g32')); // Affiche : false
                                      
  2. Exo-les-expressions-regulieres-2 :
    • Objectif : Réaliser une expression régulière permettant de vérifier si une chaîne de caractère est un numéro de téléphone belge.
    • Format des numéros de téléphone :
      • Commence soit par "+32" soit par "0".
      • Suivi d'un nombre comprenant entre 8 (tél. fixe) et 9 (tél. portable) caractères.
      • Exemples valides :
        • +485424242
        • 0485424242
        • +3210424242
        • 010424242
    • Chaînes à tester :
      
                                          // Remplacez "null" par votre expression régulière.
                                          const regexExo2 = null;
      
                                          console.log(regexExo2.test('+32485424242')); // Affiche : true
                                          console.log(regexExo2.test('0485424242')); // Affiche : true
                                          console.log(regexExo2.test('+3210424242')); // Affiche : true
                                          console.log(regexExo2.test('010424242')); // Affiche : true
                                          console.log(regexExo2.test('+32485424')); // Affiche : false
                                          console.log(regexExo2.test('048542f242')); // Affiche : false
                                          console.log(regexExo2.test('+3310424242')); // Affiche : false
                                          console.log(regexExo2.test('10424242')); // Affiche : false
                                      
  3. Exo-les-expressions-regulieres-3 :
    • Objectifs :
      • Réaliser une expression régulière permettant de récupérer le premier mot de chaque ligne.
      • Réaliser une expression régulière permettant de récupérer tous les mots contenant des lettres accentuées.
    • Chaîne à tester :
      
                                          const chaineCigaleEtFourmi = `
                                          La cigale ayant chanté
                                          Tout l'été,
                                          Se trouva fort dépourvue
                                          Quand la bise fut venue.
                                          Pas un seul petit morceau
                                          De mouche ou de vermisseau.
                                          Elle alla crier famine
                                          Chez la Fourmi sa voisine,
                                          La priant de lui prêter
                                          Quelque grain pour subsister
                                          Jusqu'à la saison nouvelle.
                                          Je vous paierai, lui dit-elle,
                                          Avant l'août, foi d'animal,
                                          Intérêt et principal.
                                          La Fourmi n'est pas prêteuse,
                                          C'est là son moindre défaut.
                                          Que faisiez-vous au temps chaud ?
                                          Dit-elle à cette emprunteuse.
                                          Nuit et jour à tout venant,
                                          Je chantais, ne vous déplaise.
                                          Vous chantiez ? j'en suis fort aise,
                                          Eh bien! dansez maintenant.
                                          `;
      
                                          // Remplacez "null" par votre expression régulière.
                                          const regexExo3_1 = null;
                                          console.log('Le premier mot de chaque ligne :')
                                          console.log(chaineCigaleEtFourmi.match(regexExo3_1)); // Affiche : Array(22) [ "La", "Tout", "Se", "Quand", "Pas", "De", "Elle", "Chez", "La", "Quelque", … ]
                                          
                                          // Remplacez "null" par votre expression régulière.
                                          const regexExo3_2 = null;
                                          console.log('Les mots avec des lettres accentuées :')
                                          console.log(chaineCigaleEtFourmi.match(regexExo3_2)); // Affiche : Array(13) [ "chanté", "été", "dépourvue", "prêter", "à", "août", "Intérêt", "prêteuse", "là", "défaut", … ]