Expressions régulières : classes, quantificateurs et groupes

Mis à jour :

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.

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.

MotifTrouve 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
\dchiffre de 0 à 9 (\D : tout le reste)
\wlettre de A à Z ou de a à z, chiffre ou tiret bas (\W : tout le reste)
\sespace, 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.

MotifSignifie
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.

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.

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.

DrapeauEffet
gtrouver toutes les correspondances, pas seulement la première
iignorer la différence entre majuscules et minuscules
m^ et $ valent pour chaque ligne
sle point trouve aussi les sauts de ligne
umode Unicode : \p{…}, et un emoji compte pour un caractère
vmode Unicode avec opérations d’ensembles dans les classes ; à utiliser à la place de u
ycollant : chercher seulement là où la correspondance précédente s’est arrêtée
dnoter 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.

Testeur de regex

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.

FonctionJavaScriptPython (re)PHP (PCRE2)
Groupe nommé(?<nom>…)(?P<nom>…)les deux formes
\d et \wASCII seulementUnicode par défautASCII sauf avec UCP
Quantificateurs possessifs et groupes atomiques (a++, (?>…))nonoui, depuis Python 3.11oui
Drapeaux en ligne comme (?i)seulement la forme limitée (?i:…), depuis ECMAScript 2025ouioui

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

  1. MDN Web Docs — Regular expressions (JavaScript guide)
  2. MDN Web Docs — Regular expression syntax cheat sheet
  3. ECMAScript® Language Specification — RegExp (Regular Expression) Objects
  4. TC39 — Finished proposals (RegExp modifiers and duplicate named groups: ECMAScript 2025)
  5. Python documentation — re: regular expression operations
  6. PCRE2 — pcre2pattern: syntax and semantics of the regular expressions
  7. OWASP — Regular expression Denial of Service (ReDoS)
  8. WHATWG HTML Standard — Valid email address
  9. RFC 5322 — Internet Message Format (October 2008)

Guides associés