Les marqueurs de regex expliqués : i, g, m, s, u, y et d
Ce que change chaque marqueur (flag) de regex en JavaScript, avec des exemples interactifs : i pour ignorer la casse, g global (et le piège de lastIndex), m multiligne, s dotAll, u unicode, y sticky et d indices, plus la façon dont Python exprime les mêmes idées.

· 5 min de lecture
/^colou?r$/i
à attraper
- color
- Colour
- COLOR
- colour
à épargner
- colr
- colours
- discolor
- kolor
Un marqueur (flag) change le comportement du motif tout entier. En JavaScript, les marqueurs se placent après la barre oblique fermante : /cat/gi. En Python, ce sont des arguments, comme re.IGNORECASE, ou des marqueurs en ligne au début du motif, comme (?i).
JavaScript en compte sept. Vous en utiliserez deux en permanence, quelques-uns de temps en temps, et l'un d'eux cache un piège dans lequel presque tout le monde est tombé. Chaque exemple est interactif : modifiez les motifs et regardez les lignes changer.
01i : ignorer la casse
Les lettres correspondent en majuscules comme en minuscules :
/^colou?r$/iDoit correspondre3/3
- color
- Colour
- COLOR
Ne doit pas2/2
- colours
- discolor
Cela vous évite d'écrire [Cc][Oo][Ll]…, et cela vaut aussi dans les classes : avec i, [a-z] accepte également les majuscules.
Python : re.IGNORECASE, re.I ou (?i).
02g : global
Sans g, une regex trouve la première correspondance et s'arrête. Avec g, des méthodes comme match, matchAll et replace agissent sur toutes les correspondances :
"a1b22c333".match(/\d+/); // ["1"], plus index and input
"a1b22c333".match(/\d+/g); // ["1", "22", "333"]
"a-b-c".replace(/-/, "+"); // "a+b-c"
"a-b-c".replace(/-/g, "+"); // "a+b+c"
Python n'a pas de g. À la place, vous choisissez la fonction : re.search trouve une correspondance, re.findall et re.finditer les trouvent toutes, et re.sub remplace tout par défaut.
Le piège de lastIndex
Une regex avec g (ou y) mémorise où sa dernière correspondance s'est terminée, dans lastIndex, et le test() suivant repart de là. Réutilisez une telle regex sur plusieurs chaînes et les résultats se mettent à alterner :
const hasDigit = /\d/g;
hasDigit.test("a1"); // true, lastIndex is now 2
hasDigit.test("b2"); // false: the search starts at index 2, past the "2"
hasDigit.test("b2"); // true again, lastIndex had reset to 0
La solution est simple : ne mettez pas g sur une regex que vous n'utilisez qu'avec test(). Vous n'en avez pas besoin pour vérifier si quelque chose correspond.
03m : multiligne
^ et $ correspondent au début et à la fin de chaque ligne au lieu du texte entier. L'article sur les ancres et le mode multiligne traite le sujet en détail.
"one\ntwo".match(/^\w+$/gm); // ["one", "two"]
Python : re.MULTILINE, re.M ou (?m).
04s : dotAll
Normalement, . correspond à n'importe quel caractère sauf un saut de ligne. Avec s, il accepte aussi les sauts de ligne :
/start.*end/.test("start\nend"); // false
/start.*end/s.test("start\nend"); // true
Avant l'arrivée de s, on écrivait [\s\S] pour dire « absolument n'importe quel caractère », et on le croise encore dans du code ancien.
Python : re.DOTALL, re.S ou (?s).
05u : unicode
u fait travailler le motif sur des caractères Unicode entiers plutôt que sur des morceaux UTF-16, et active les échappements de propriété comme \p{L} (n'importe quelle lettre, dans n'importe quelle écriture) :
/^\p{L}+$/uDoit correspondre4/4
- hello
- café
- Zürich
- Москва
Ne doit pas2/2
- R2D2
- two words
Il fait aussi correspondre . à un emoji entier plutôt qu'à une moitié d'emoji, et il rend l'analyseur strict : un échappement inutile comme \- hors d'une classe devient une erreur de syntaxe au lieu d'être ignoré en silence. Le marqueur v, plus récent en JavaScript, est un sur-ensemble plus strict de u qui permet des opérations d'ensembles dans les classes.
Le module re de Python gère l'Unicode par défaut mais n'a pas de \p{…}. Le module tiers regex l'ajoute.
06y : sticky
Avec y, une correspondance doit commencer exactement à lastIndex, pas n'importe où après. Il sert surtout aux analyseurs lexicaux (tokenizers) qui parcourent une chaîne morceau par morceau :
const word = /\w+/y;
word.lastIndex = 0;
word.exec("hi there"); // ["hi"], lastIndex is now 2
word.exec("hi there"); // null: index 2 is a space, and y won't skip ahead
07d : indices
d ajoute à chaque correspondance un tableau indices avec le début et la fin de la correspondance et de chaque groupe :
const m = /(\d+)-(\d+)/d.exec("pages 12-30");
m.indices[0]; // [6, 11], the whole match
m.indices[1]; // [6, 8], the first group, "12"
Pratique pour surligner les correspondances dans un éditeur. Python le propose d'origine : m.span(1).
08À vous de jouer
Utilisez le marqueur i pour que votre solution reste courte :
Attrapez yes quelle que soit la casse, et rien d'autre.
Cibles · 0/5 attrapées
- yescible
- Yescible
- YEScible
- yEscible
- yeScible
Innocents · erreurs : 0
- yesterdayinnocent
- eyesinnocent
- noinnocent
- yeinnocent
- y e sinnocent
Tapez une regex — le plateau se met à jour en direct.
09Récapitulatif
iignore la casse.mapplique^et$à chaque ligne.spermet à.d'accepter les sauts de ligne.gtrouve toutes les correspondances, mais ne l'utilisez pas avectest()sur une regex réutilisée.ugère tout l'Unicode et active\p{L}.yne trouve une correspondance qu'àlastIndex.dajoute les positions des correspondances.- Python :
re.I,re.M,re.S, ou en ligne(?i),(?m),(?s). Pas deg: utilisezfindallousub.
10Continuez à vous entraîner
- La section du guide sur les marqueurs propose un aide-mémoire, et la section unicode approfondit
u. - Dompter les lignes est un pack d'entraînement où les marqueurs comptent.
- Essayez la chasse du jour, ou parcourez les plateaux passés dans les archives.