09 - Les flags
Ce que tu vas apprendre
- Les 7 flags disponibles en JavaScript : g, i, m, s, u, v, d
- Le piège du flag
gaveclastIndex - Le flag
uet le support Unicode - Le flag
v(unicodeSets) et les opérations sur les ensembles - Combiner les flags efficacement
Prerequisites
Les flags modifient le comportement global d'une regex. Tu les mets apres le dernier slash : /pattern/flags. La plupart des développeurs connaissent g et i, mais les autres flags sont tout aussi utiles. Et le flag g cache un piège vicieux que la majorite des gens decouvrent par un bug en production.
g - Global
Sans g, la regex s'arrêté au premier match. Avec g, elle trouve tous les matches :
javascript"aaa bbb aaa".match(/aaa/); // ["aaa"] (premier seulement)
"aaa bbb aaa".match(/aaa/g); // ["aaa", "aaa"] (tous)
Simple en apparence. Mais g change le comportement de .test() et .exec() de manière inattendue :
javascriptconst regex = /abc/g;
regex.test("abc xyz abc"); // true (lastIndex = 3)
regex.test("abc xyz abc"); // true (lastIndex = 11)
regex.test("abc xyz abc"); // false (lastIndex = 0)
regex.test("abc xyz abc"); // true (lastIndex = 3)
Chaque appel a .test() reprend là où le précédent s'est arrêté. La regex garde un état interne via la propriété lastIndex. Ca signifie que si tu utilises la meme regex g dans une boucle de validation, tu auras des résultats alternant entre true et false.
javascript// BUG classique
const emailRegex = /\w+@\w+\.\w+/g;
function isValid(email) {
return emailRegex.test(email); // lastIndex persiste entre les appels !
}
isValid("user@test.com"); // true
isValid("user@test.com"); // false (!!)
isValid("user@test.com"); // true
La regle : n'utilise jamais g avec .test() si tu reutilises la meme instance de regex. Soit tu créés une nouvelle regex a chaque appel, soit tu retires le flag g.
i - Case Insensitive
Ignore la casse :
javascript/hello/i.test("Hello"); // true
/hello/i.test("HELLO"); // true
/hello/i.test("hElLo"); // true
Rien de surprenant. Mais attention avec les caractères Unicode : le flag i seul ne gere pas les equivalences de casse Unicode. Pour ca, il faut combiner avec u.
javascript/\u00e9/i.test("\u00c9"); // true (e avec accent)
/cafe/i.test("CAFE"); // true
m - Multiline
Change le comportement de ^ et $. Sans m, ils matchent le début et la fin de la chaîne entière. Avec m, ils matchent le début et la fin de chaque ligne :
javascriptconst texte = "premiere ligne\ndeuxieme ligne\ntroisieme ligne";
texte.match(/^\w+/g); // ["premiere"] (debut de chaine)
texte.match(/^\w+/gm); // ["premiere", "deuxieme", "troisieme"] (debut de chaque ligne)
texte.match(/\w+$/g); // ["ligne"] (fin de chaine)
texte.match(/\w+$/gm); // ["ligne", "ligne", "ligne"] (fin de chaque ligne)
Le flag m est indispensable quand tu traites du texte multiligne. Sans lui, tu rates tout ce qui n'est pas sur la première ou dernière ligne.
s - DotAll
Par défaut, le point . matche tout sauf les retours a la ligne (\n). Le flag s change ca :
javascriptconst html = "<div>\n contenu\n</div>";
/<div>.*<\/div>/.test(html); // false (le . ne passe pas le \n)
/<div>.*<\/div>/s.test(html); // true (le . matche tout, y compris \n)
Avant ES2018, on utilisait [\s\S] comme remplacement du "vrai point" :
javascript/<div>[\s\S]*<\/div>/.test(html); // true (le hack pre-ES2018)
Le flag s est plus propre. Utilise-le quand tu travailles avec du texte multiligne et que tu veux que . matche vraiment tout.
u - Unicode
Le flag u active le support Unicode complet. Sans lui, JavaScript traite les chaînes comme des sequences de code units UTF-16, ce qui casse avec les caractères hors du Basic Multilingual Plane :
javascript// Sans u : un emoji est vu comme 2 caracteres
/^.$/.test("a]"); // false (2 code units)
// Avec u : un emoji est vu comme 1 caractere
/^.$/u.test("a]"); // Depends on the emoji
// Plus concretement
"😀".length; // 2 (JS voit 2 code units)
/^.$/u.test("😀"); // true (u voit 1 code point)
/^.$/.test("😀"); // false
Le flag u debloque aussi les propriétés Unicode \p{...} :
javascript// Matcher toutes les lettres Unicode (pas juste ASCII)
/\p{Letter}/u.test("e"); // true
/\p{Letter}/u.test("e"); // true (accent)
/\p{Letter}/u.test("7"); // false
// Matcher les emojis
/\p{Emoji}/u.test("😀"); // true
// Matcher les lettres grecques
/\p{Script=Greek}/u.test("α"); // true
Sur paltemps.fr, le flag u est systématique dans mes regex. On vit dans un monde Unicode, et ignorer ca c'est s'exposer a des bugs subtils avec les accents, les emojis et les alphabets non-latins.
v - UnicodeSets (ES2024)
Le flag v est l'évolution du flag u. Il apporte les opérations sur les ensembles dans les classes de caractères :
javascript// Soustraction : lettres sauf les voyelles
/[\p{Letter}--[aeiouAEIOU]]/v.test("b"); // true
/[\p{Letter}--[aeiouAEIOU]]/v.test("a"); // false
// Intersection : caracteres qui sont a la fois lettre et ASCII
/[\p{Letter}&&\p{ASCII}]/v.test("a"); // true
/[\p{Letter}&&\p{ASCII}]/v.test("e"); // false (accent, pas ASCII)
// Union imbriquee
/[[\p{Script=Greek}][\p{Script=Latin}]]/v.test("α"); // true
/[[\p{Script=Greek}][\p{Script=Latin}]]/v.test("a"); // true
Le flag v est incompatible avec u. Tu utilises l'un ou l'autre, jamais les deux.
d - HasIndices
Le flag d ajoute les positions de début et fin de chaque groupe capture :
javascriptconst regex = /(?<annee>\d{4})-(?<mois>\d{2})/d;
const match = "date: 2026-03".match(regex);
console.log(match.indices[0]); // [6, 13] (match complet)
console.log(match.indices[1]); // [6, 10] (groupe 1: annee)
console.log(match.indices.groups.annee); // [6, 10]
console.log(match.indices.groups.mois); // [11, 13]
Utile pour du syntax highlighting ou quand tu dois savoir exactement ou chaque capture se situe dans la chaîne originale.
Combiner les flags
Les flags se cumulent :
javascript// Recherche globale, insensible a la casse, multiligne, Unicode
const regex = /^bonjour/gimu;
// DotAll + global pour parser du HTML multiligne
const htmlRegex = /<div class="content">.*?<\/div>/gs;
Les combinaisons les plus courantes :
gi: trouver tous les matches sans tenir compte de la cassegm: trouver des patterns au début/fin de chaque lignegs: matcher à travers les retours a la lignegu: recherche globale avec support Unicode
Verifier les flags d'une regex
javascriptconst regex = /test/giu;
console.log(regex.flags); // "giu"
console.log(regex.global); // true
console.log(regex.ignoreCase); // true
console.log(regex.unicode); // true
console.log(regex.multiline); // false
Résumé
g: tous les matches, mais attention au piège delastIndexavec.test()i: insensible a la cassem:^et$matchent par ligne au lieu de la chaîne entières: le point.matche aussi\nu: support Unicode complet et propriétés\p{}v: opérations sur les ensembles dans les classes de caractères (ES2024)d: indices de position de chaque capture- Ne jamais réutiliser une regex
gavec.test()sans reset dulastIndex
Article précédent : 08 - Lookahead et lookbehind Article suivant : 10 - Regex en JavaScript