Quelle variante de regex cet outil teste-t-il ?+
Celle qui tourne déjà dans votre navigateur. Aucun moteur n'est intégré à cette page : votre motif est transmis au constructeur RegExp de l'environnement d'exécution JavaScript, et les correspondances que vous voyez sont celles qu'obtiendra votre code. Les résultats sont donc exacts pour JavaScript, TypeScript, Node, Deno et Bun. Pour tout le reste, ils ne sont qu'approximatifs. Le module re de Python, PCRE en PHP et Perl, RE2 de Go, la crate regex de Rust, .NET, Java, grep, sed et ripgrep diffèrent tous, parfois par la syntaxe et parfois par le sens d'une même syntaxe. Si le motif est destiné à un autre langage, testez-le dans ce langage avant de le livrer.
Quelle est la différence entre les quantificateurs gourmands et paresseux ?+
Un quantificateur gourmand prend tout ce qu'il peut, puis rend les caractères un par un jusqu'à ce que le reste du motif convienne. Un quantificateur paresseux (qui s'écrit en ajoutant un point d'interrogation : *? +? ?? {n,m}?) prend le moins possible et ne grandit que lorsqu'il y est forcé. La démonstration classique est /<.+>/ sur « <a><b> » : le .+ gourmand avale tout jusqu'à la fin, revient en arrière jusqu'au dernier « > » et renvoie « <a><b> » comme une seule correspondance. Remplacez-le par /<.+?>/ et vous obtenez « <a> », puis « <b> ». Aucun n'est plus correct que l'autre ; ils répondent à des questions différentes. La règle pratique : le gourmand est le bon choix par défaut quand le délimiteur est unique, et le paresseux quand il se répète.
Qu'est-ce que le backtracking catastrophique ?+
C'est ce qui se produit quand un motif peut découper le même texte de très nombreuses façons et que la correspondance finit par échouer. JavaScript cherche les correspondances par backtracking : en cas d'échec, il réessaie donc toutes les combinaisons restantes avant d'abandonner. Le déclencheur classique est une répétition dans une répétition, comme /(a+)+$/ sur une longue suite de « a » suivie d'un seul « b ». Il existe un nombre exponentiel de façons de répartir 30 « a » en groupes d'un ou plusieurs, et le moteur les essaie toutes avant de conclure que le « $ » ne peut pas correspondre. Trente caractères prennent quelques millisecondes ; quarante prennent environ mille fois plus. Les solutions : empêcher les répétitions intérieure et extérieure de correspondre au même texte, remplacer un groupe quantifié par une classe de caractères, ou ancrer le motif pour que l'échec soit détecté tôt. Cette page analyse votre motif à la recherche de ces formes et les nomme avant de l'exécuter.
Pourquoi le lookbehind est-il arrivé si tard en JavaScript ?+
Le lookahead fait partie du langage depuis le début, mais le lookbehind n'est arrivé qu'avec ES2018 (plus de vingt ans plus tard), et jusqu'à ce que Safari le prenne en charge en 2023, un motif qui l'utilisait déclenchait une erreur de syntaxe sur un navigateur que beaucoup de sites devaient encore prendre en charge. Ce retard s'explique en partie par le ralentissement général de l'évolution du langage entre l'abandon d'ES4 et ES6, et en partie par le fait que le lookbehind est réellement plus difficile à implémenter : le moteur doit chercher à reculons depuis la position courante. L'implémentation de JavaScript s'est finalement révélée meilleure que la plupart, car contrairement à PCRE, au module re de Python et à Java, elle autorise un lookbehind de longueur variable. /(?<=\$\d+ )item/ est valide ici et rejeté d'emblée par ces moteurs. Si l'un de vos motifs doit fonctionner dans un environnement ancien, la solution traditionnelle consiste à capturer le contexte précédent dans un groupe et à l'ignorer ensuite.
Quelle est la différence entre les drapeaux u et v ?+
Le drapeau u, introduit par ES2015, fait passer le motif en mode Unicode : les caractères astraux comme les emoji comptent pour une unité au lieu de deux moitiés UTF-16, \u{1F600} devient valide, les échappements de propriété \p{…} sont débloqués, et les échappements sans signification deviennent des erreurs de syntaxe au lieu d'être ignorés en silence. Le drapeau v, introduit par ES2024, est un sur-ensemble qui ajoute une notation ensembliste dans les classes de caractères (différence avec --, intersection avec && et propriétés de chaînes de plusieurs caractères), ce qui permet d'écrire [\p{Letter}--[a-z]] pour dire « n'importe quelle lettre sauf une minuscule ASCII ». Les deux drapeaux s'excluent mutuellement : une regex est en mode u ou en mode v, jamais les deux. Cette page propose u et pas v, car une paire de boutons qui s'annulent silencieusement est une moins bonne interface qu'une interface honnête sur sa portée.
Pourquoi ma regex globale saute-t-elle une correspondance sur deux ?+
Parce qu'une regex portant le drapeau g ou y a un état. Elle stocke une propriété lastIndex, et exec comme test partent de là et la mettent à jour en cas de succès. Stockez-en une dans une constante de niveau module, appelez test deux fois sur la même chaîne, et le second appel commence à mi-chemin et renvoie false. Le même bug survient quand une regex globale est réutilisée d'un élément à l'autre dans une boucle. Il y a trois façons d'en sortir : créer la regex à neuf là où elle est utilisée, remettre lastIndex à 0 avant chaque appel, ou utiliser matchAll et String.match, qui ne laissent pas traîner le curseur là où vous pourriez trébucher dessus. Cette page évite complètement le problème en compilant une copie de travail privée à chaque exécution, si bien que la regex que vous regardez n'est jamais celle qui est modifiée.
Que peut faire PCRE que les regex JavaScript ne peuvent pas faire ?+
Plusieurs choses, et savoir lesquelles évite bien des débogages déroutants quand vous copiez un motif d'un moteur à l'autre. Il n'y a pas de groupes atomiques : le (?>…) de PCRE s'engage sur une correspondance et refuse d'y revenir par backtracking, ce qui est le correctif manuel classique du backtracking catastrophique, et le seul substitut en JavaScript est un lookahead qui enveloppe une capture. Il n'y a pas de quantificateurs possessifs (a*+), pour la même raison. Il n'y a pas de récursion (?R) ni d'appels de sous-routines, donc les parenthèses équilibrées sont hors de portée. Il n'y a pas de modificateurs en ligne : (?i) au milieu d'un motif est une erreur de syntaxe, car un drapeau JavaScript s'applique à toute la regex ou pas du tout. Il n'y a pas de conditionnelles, pas d'ancres \A \z \Z, pas de classes POSIX comme [[:alpha:]], et pas de mode commentaire. Ce que JavaScript possède et que beaucoup de moteurs n'ont pas, c'est le lookbehind de longueur variable.
\d signifie-t-il la même chose partout ?+
Non, et cette différence est une vraie source de failles de sécurité. En JavaScript, \d vaut exactement [0-9], toujours, avec ou sans le drapeau u. En .NET et en Python 3, \d correspond par défaut à tout caractère doté de la propriété Unicode de chiffre décimal, ce qui inclut les chiffres indo-arabes ٠١٢, les chiffres devanagari et les chiffres pleine chasse 012. Un validateur écrit en Python qui accepte ٢٠٢٦ et un validateur JavaScript qui le rejette ne seront pas d'accord sur la même entrée, et c'est précisément le genre d'incohérence qui est exploité. La même prudence s'applique à \w, qui vaut ici [A-Za-z0-9_] et ne considère donc pas « é » comme un caractère de mot, et à \b, qui est défini à partir de \w et tombe donc au milieu de « naïve ». Si vous voulez une sémantique Unicode en JavaScript, vous devez la demander explicitement : \p{Nd} avec le drapeau u pour les chiffres, \p{L} pour les lettres.
Quand faut-il arrêter d'utiliser une expression régulière ?+
Quand ce que vous recherchez peut s'imbriquer. Les expressions régulières au sens formel ne savent pas compter, et même si les références arrière poussent le moteur de JavaScript au-delà d'un langage strictement régulier, il ne peut toujours pas reconnaître une structure équilibrée. Cela exclut HTML, XML, JSON, le code source et tout langage à parenthèses, non pas parce que le motif est difficile à écrire, mais parce qu'aucun motif n'existe. Utilisez DOMParser, JSON.parse ou un vrai analyseur. Trois signaux plus discrets vont dans le même sens : le motif dépasse une ou deux lignes et personne ne peut le lire, il faut un commentaire pour expliquer chaque clause, ou il accumule les cas particuliers pour des entrées qu'il était censé déjà gérer. Une expression régulière est à son meilleur pour trouver et valider des fragments plats et bien formés (une date, une couleur hexadécimale, un préfixe de journal), et à son pire quand elle se fait passer pour une grammaire.
Que signifient $1, $&, $` et $' dans un remplacement ?+
Ce sont les motifs de substitution que String.replace comprend dans la chaîne de remplacement. De $1 à $99, ils insèrent le texte du groupe de capture portant ce numéro, et $<name> fait de même pour un groupe nommé. $& insère la correspondance entière. $` insère tout ce qui précède la correspondance et $' tout ce qui la suit ; les deux sont étonnamment utiles pour encadrer du texte et étonnamment faciles à déclencher par accident, car une barre oblique inverse ne les échappe pas. $$ insère un seul signe dollar littéral. Deux règles piègent souvent : une référence à un groupe qui n'existe pas est laissée telle quelle dans la sortie au lieu de lever une erreur, et $12 désigne le groupe 12 si le motif compte douze groupes, et le groupe 1 suivi du caractère « 2 » sinon. Cette page les développe tous dans l'aperçu et signale toute référence qu'elle n'a pas pu résoudre.