Expressions régulières : classes, quantificateurs et groupes
Une expression régulière, ou regex, est un petit motif qui décrit du texte : « quatre chiffres, un tiret, deux chiffres », ou « un mot qui commence par une majuscule ». Les programmes s’en servent pour chercher, pour vérifier une saisie et pour extraire des morceaux d’une ligne. Ce guide explique les pièces d’un motif, avec des exemples à coller dans le testeur de regex, puis les pièges : les motifs qui trouvent plus que prévu, ceux qui peuvent durer une éternité, et les différences entre les moteurs de JavaScript, Python et PHP. Les exemples utilisent la syntaxe de JavaScript, celle du testeur et de tous les navigateurs.
Les caractères qui veulent dire autre chose
La plupart des caractères d’un motif se représentent eux-mêmes : chat trouve les lettres c, h, a et t dans cet ordre. Quatorze non, car ils ont un rôle dans le motif : . ^ $ * + ? ( ) [ ] { } | \ et, dans du code JavaScript, la barre oblique qui ferme le motif. Pour en chercher un tel quel, mettez une barre oblique inverse devant.
1.5Trouve 1.5, mais aussi 1x5 et 1-5 : le point représente n’importe quel caractère.1\.5Trouve seulement 1.5 : la barre oblique inverse fait du point un point.\$\d+Trouve $30 : un signe dollar échappé, puis des chiffres.
Les classes de caractères
Une classe trouve un caractère parmi un ensemble. Les crochets donnent l’ensemble vous-même ; une barre oblique inverse et une lettre en donnent un tout prêt ; la lettre en majuscule signifie l’inverse.
| Motif | Trouve un… |
|---|---|
[aeiou] | voyelle sans accent : a, e, i, o ou u |
[^aeiou] | caractère qui n’en fait pas partie, espaces et chiffres compris |
[a-z0-9] | lettre minuscule de a à z, ou un chiffre |
\d | chiffre de 0 à 9 (\D : tout le reste) |
\w | lettre de A à Z ou de a à z, chiffre ou tiret bas (\W : tout le reste) |
\s | espace, tabulation, saut de ligne ou autre blanc (\S : tout le reste) |
. | caractère sauf un saut de ligne (n’importe lequel avec le drapeau s) |
\p{L} | lettre de n’importe quel alphabet, avec le drapeau u ou v |
En JavaScript, \d et \w ne connaissent que l’alphabet latin de base : \w+ coupe Noël en No et l, et \d ne trouve pas le chiffre arabe oriental ٣. Avec le drapeau u, \p{L}+ trouve Noël en entier et \p{Nd} trouve les chiffres de toutes les écritures. Python 3 fait l’inverse : sur du texte ordinaire, son \d et son \w couvrent déjà Unicode, sauf avec le drapeau ASCII. Le moteur PCRE2 de PHP reste en ASCII tant que les propriétés Unicode ne sont pas activées, par exemple avec (*UCP) au début du motif.
Les quantificateurs : combien de fois
Un quantificateur indique combien de fois l’élément qui le précède peut se répéter. Il s’applique à un caractère, une classe ou un groupe entre parenthèses.
| Motif | Signifie |
|---|---|
a* | zéro ou plus |
a+ | un ou plus |
a? | zéro ou un, c’est-à-dire facultatif |
a{3} | exactement trois |
a{3,} | trois ou plus |
a{2,4} | de deux à quatre |
Les quantificateurs sont gourmands : ils prennent tout ce qu’ils peuvent et ne rendent que ce dont le reste du motif a besoin. Sur <b>gras</b>, le motif <.+> trouve toute la chaîne, du premier < au dernier >. Un point d’interrogation derrière le rend paresseux, il prend le moins possible : <.+?> trouve <b> puis </b>. colou?r trouve les deux orthographes anglaises, color et colour, et \d{3,} trouve les nombres de trois chiffres ou plus.
Les ancres et les limites de mot
Une ancre trouve une position, pas un caractère. ^ est le début du texte et $ la fin ; avec le drapeau m, ils deviennent le début et la fin de chaque ligne. \b est une limite de mot, l’endroit entre un caractère de mot et autre chose, donc \bchat\b trouve chat comme mot mais pas dans chaton. Sans ancres, un motif qui sert à valider accepte aussi un texte avec des caractères en trop autour : \d{4} trouve quatre chiffres dans abc12345, alors que ^\d{4}$ n’accepte qu’exactement quatre chiffres.
\bchat\bSur « chat chaton chat. » : deux correspondances, les deux mots chat.^\d{4}$Accepte 2026 ; refuse 12026 et 2026a.
Groupes, alternatives et références arrière
Les parenthèses regroupent une partie du motif pour qu’un quantificateur ou une alternative s’applique à tout le groupe, et elles capturent le texte trouvé pour qu’un programme puisse le lire : (\d{4})-(\d{2})-(\d{2}) capture séparément l’année, le mois et le jour. (?:…) regroupe sans capturer, et (?<annee>\d{4}) donne un nom à la capture.
La barre verticale veut dire « ou », et c’est ce qui a la priorité la plus faible : ^chat|nuit$ veut dire « chat au début » ou « nuit à la fin », donc il trouve chat dans chaton et nuit dans minuit. Pour dire « le texte entier est chat ou nuit », regroupez les alternatives : ^(?:chat|nuit)$.
Une référence arrière trouve le même texte qu’un groupe a déjà capturé : (\w)\1 trouve une lettre suivie d’elle-même, ll et tt dans ballotter, et \k<nom> fait de même pour un groupe nommé.
Assertions avant et arrière
Une assertion (lookahead ou lookbehind) vérifie ce qui vient avant ou après une position sans l’inclure dans la correspondance. (?=…) exige que quelque chose suive, (?!…) l’interdit ; (?<=…) exige que quelque chose précède, (?<!…) l’interdit. Elles servent à repérer un nombre par son unité ou sa devise, ou à cumuler plusieurs conditions sur le même texte.
\d+(?=%)Sur « 20% de 500 » : trouve 20, le nombre suivi d’un signe pour cent, sans le signe.(?<=€)\d+Sur « €25 et $30 » : trouve 25, le montant après un signe euro.^(?=.*\d).{8,}$Accepte motdepasse1 et refuse motdepasse : au moins huit caractères, dont un chiffre.
Les drapeaux
Les drapeaux changent la façon dont tout le motif s’applique. En JavaScript, ils suivent la barre oblique de fin, comme dans /chat/gi ; dans le testeur, ils ont leur propre champ.
| Drapeau | Effet |
|---|---|
g | trouver toutes les correspondances, pas seulement la première |
i | ignorer la différence entre majuscules et minuscules |
m | ^ et $ valent pour chaque ligne |
s | le point trouve aussi les sauts de ligne |
u | mode Unicode : \p{…}, et un emoji compte pour un caractère |
v | mode Unicode avec opérations d’ensembles dans les classes ; à utiliser à la place de u |
y | collant : chercher seulement là où la correspondance précédente s’est arrêtée |
d | noter où chaque groupe commence et finit |
Vérifier des e-mails, des dates et d’autres formats
Une regex peut vérifier la forme d’une saisie, pas sa réalité. La norme HTML définit ce qu’accepte un <input type="email"> avec son propre motif, et dit ouvertement qu’elle s’écarte volontairement du RFC 5322, la norme du format des e-mails, qui autorise des formes comme des noms entre guillemets avec des espaces que presque personne n’utilise. Il accepte ana@example.com et aussi ana@localhost ; il refuse ana@my_domain.example, car un nom de domaine ne peut pas contenir de tiret bas. Seul un message dit si la boîte existe.
C’est pareil pour les dates : ^\d{4}-\d{2}-\d{2}$ accepte 2026-02-31, qui n’existe pas. Vérifiez la forme avec le motif, puis laissez une fonction de dates décider si la date est valide. Et n’analysez pas du HTML ou du JSON avec des expressions régulières : les structures imbriquées demandent un analyseur.
Quand un motif ne finit jamais
La plupart des moteurs, dont ceux de JavaScript, Python et PHP, fonctionnent par retour arrière (backtracking) : quand un chemin échoue, ils reviennent en arrière et essaient une autre façon de répartir le texte entre les parties du motif. Un groupe qui répète quelque chose qui se répète déjà, comme ^(a+)+$, peut se répartir d’un nombre de façons qui double à chaque caractère en plus. Sur une suite de a terminée par un point d’exclamation, le motif ne peut jamais correspondre, mais le moteur essaie toutes les répartitions avant d’abandonner. L’OWASP appelle cela un déni de service par expression régulière, ReDoS, et cite des motifs comme (a+)+$, ([a-zA-Z]+)*$ et (a|aa)+$.
Le remède consiste à supprimer l’ambiguïté : ^a+$ décrit le même texte et échoue tout de suite. Évitez les quantificateurs imbriqués et les alternatives qui peuvent trouver les mêmes caractères, et n’exécutez jamais un motif fourni par un utilisateur sans limite de temps. Le testeur de regex lance chaque recherche dans un worker séparé et l’arrête au bout d’une demi-seconde : un motif de ce genre est signalé au lieu de bloquer la page.
Tous les moteurs ne se valent pas
Les bases ci-dessus fonctionnent presque partout, mais les détails changent d’un langage à l’autre. Un motif écrit pour un moteur doit être testé dans l’autre avant de s’y fier.
| Fonction | JavaScript | Python (re) | PHP (PCRE2) |
|---|---|---|---|
| Groupe nommé | (?<nom>…) | (?P<nom>…) | les deux formes |
| \d et \w | ASCII seulement | Unicode par défaut | ASCII sauf avec UCP |
| Quantificateurs possessifs et groupes atomiques (a++, (?>…)) | non | oui, depuis Python 3.11 | oui |
| Drapeaux en ligne comme (?i) | seulement la forme limitée (?i:…), depuis ECMAScript 2025 | oui | oui |
Le lookbehind diffère aussi : JavaScript en accepte un de longueur variable, comme (?<=[a-z]+), alors que Python exige une largeur fixe et le refuse. Python écrit aussi les barres obliques inverses autrement dans le code : une chaîne brute, r"\d+", les garde telles quelles, tandis que les motifs JavaScript entre barres obliques n’ont pas besoin de les doubler. Dans une chaîne JavaScript passée à new RegExp(), chaque barre oblique inverse doit être écrite deux fois.
Questions fréquentes
Pourquoi mon motif ne trouve-t-il qu’une correspondance ?
En JavaScript, la recherche s’arrête à la première correspondance sans le drapeau g. Dans le testeur, ajoutez g aux drapeaux.
Pourquoi \w ne trouve-t-il pas les lettres accentuées ?
Parce qu’en JavaScript \w ne désigne que A à Z, a à z, les chiffres et le tiret bas. Utilisez \p{L} avec le drapeau u pour les lettres de n’importe quel alphabet.
Comment chercher un point, une parenthèse ou un point d’interrogation ?
Mettez une barre oblique inverse devant : \. \( \? et ainsi de suite. Entre crochets, la plupart perdent leur sens, donc [.?] trouve un point ou un point d’interrogation.
Une expression régulière peut-elle valider un e-mail ?
Seulement sa forme. Le motif de la norme HTML est un bon choix pour les formulaires ; seul un message envoyé dit si l’adresse reçoit du courrier.
Pourquoi mon motif a-t-il bloqué le programme ?
Il répète sans doute un groupe qui se répète déjà, comme (a+)+, et le texte correspond presque. Réécrivez-le sans quantificateurs imbriqués, et exécutez les motifs des utilisateurs avec une limite de temps.
Références
- MDN Web Docs — Regular expressions (JavaScript guide)
- MDN Web Docs — Regular expression syntax cheat sheet
- ECMAScript® Language Specification — RegExp (Regular Expression) Objects
- TC39 — Finished proposals (RegExp modifiers and duplicate named groups: ECMAScript 2025)
- Python documentation — re: regular expression operations
- PCRE2 — pcre2pattern: syntax and semantics of the regular expressions
- OWASP — Regular expression Denial of Service (ReDoS)
- WHATWG HTML Standard — Valid email address
- RFC 5322 — Internet Message Format (October 2008)
Guides associés
- Les adresses IP expliquées : IPv4, IPv6 et les plages réservées
- Les sous-réseaux et le CIDR expliqués : préfixes, masques et hôtes utilisables
- Les enregistrements DNS expliqués : A, AAAA, CNAME, MX, TXT et NS
- Un site est-il en panne, ou est-ce chez vous ? Comment vérifier, étape par étape
- Codes de statut HTTP et erreurs Cloudflare : ce que signifient 403, 404, 429, 500, 503 et 521
- Les timestamps Unix et les fuseaux horaires expliqués
- Compter les dates : jours entre deux dates, années bissextiles et semaines ISO
- Fuseaux horaires et heure d’été : réunions entre villes
- Les formats d’image expliqués : JPEG, PNG, WebP, AVIF et HEIC
- La taille d’une image expliquée : pixels, DPI, poids et qualité
- Les photos de téléphone expliquées : HEIC, métadonnées EXIF et vie privée
- La robustesse des mots de passe expliquée : longueur, entropie et phrases de passe
- Le hachage expliqué : SHA-256, sommes de contrôle et mots de passe
- Les JSON Web Tokens expliqués : revendications, signatures, validation sûre
- Les clés API expliquées : longueur, format, stockage et rotation
- Les UUID expliqués : v4, v7 et comment choisir la bonne version
- Les QR codes expliqués : capacité, correction d’erreurs et taille d’impression
- Les pourcentages et la TVA expliqués : ajouter, retirer et cumuler
- Erreurs JSON courantes et comment les corriger
- Les fichiers CSV expliqués : séparateurs, guillemets, encodage et Excel
- Les encodages de texte expliqués : UTF-8, Base64 et encodage d’URL
- Modifier des PDF dans le navigateur : ce que la fusion, la division et la conversion conservent