Aller au contenu
DevTools / Testeur d'expressions régulières

Testeur d'expressions régulières

Regular expressions are write-only unless you can see what they match. This tester highlights every match as you type, lists each capture group and named group separately, previews the result of a replacement string including backreferences, and warns about the mistakes that do not produce an error but do produce wrong answers — an unescaped dot, a greedy quantifier where a lazy one was intended, or a pattern anchored at one end only.

Fonctionne entièrement dans votre navigateur — rien n'est envoyé.

//gi

Pattern library

Test string
Matches: 2
ada@example.com, not-an-email, grace@dev.co.uk

Capture groups

#1 @ 0ada@example.com
#2 @ 31grace@dev.co.uk

Comment ça marche

Matching is driven by JavaScript's own regular expression engine, the one that will run your pattern in a browser or in Node, so the result you see is the result you will get. That matters because engines differ in ways that are easy to miss: lookbehind is supported in JavaScript and in PCRE but not in Go's RE2, and possessive quantifiers and atomic groups are PCRE-only. If your production code runs on a different engine, testing here tells you about the pattern's logic but not about its portability.

Flags change the meaning of a pattern more than most people expect. The g flag finds every match rather than stopping at the first, and its absence is why a replace call so often changes only one occurrence. The i flag makes matching case-insensitive, m makes ^ and $ match at line boundaries instead of only at the start and end of the whole string, s makes the dot match newlines, and u enables full Unicode mode where a character class understands code points rather than UTF-16 units — which is the difference between matching an emoji correctly and matching half of it.

Capture groups are numbered by the order of their opening parentheses, and nested groups are numbered by where they open, not where they close. A group followed by a quantifier captures only its final iteration, which is the classic reason a pattern that looks like it should capture a list returns one item. Named groups with the (?<name>...) syntax avoid the counting problem entirely and this tool lists them by name alongside their positions, so the relationship between the pattern and the extracted values is visible rather than inferred.

Two failure modes deserve explicit warning. A pattern with nested quantifiers such as (a+)+b can take exponential time on a non-matching input, which is catastrophic backtracking and a genuine denial-of-service vector when the pattern runs against user input — a 30-character string can hang a process. The other is the unanchored pattern: \d{4} will happily match the first four digits of a longer number, and adding ^ and $ is usually what was intended. Both are reported rather than left for you to discover.

Cas d'usage courants

  • Build and debug a validation pattern for an email address, URL, phone number or semantic version.
  • Extract fields from log lines by writing a pattern against real samples rather than guessing.
  • Check which capture group a value landed in before writing the code that reads it.
  • Preview a replace operation with backreferences to confirm the output format before applying it to a file.
  • Test whether a pattern is catastrophically backtracking before shipping it to a server.
  • Convert an unreadable pattern into a plain-language explanation for a code review or a comment.

Dernière mise à jour: 2026-10-14 — le corps de l'article est affiché en anglais ; l'interface est traduite.

Questions fréquentes

Why does my replace only change the first occurrence?

Because the global flag is missing. Without g, a regular expression stops at the first match, and both String.replace and String.matchAll behave accordingly. Adding the flag makes the engine continue from the end of each match. The related surprise is that repeating a match can loop forever if the pattern can match an empty string, which is why a global pattern that matches nothing but the empty string needs an explicit guard.

What is catastrophic backtracking?

It is what happens when a backtracking engine explores an exponential number of ways to match a pattern against an input that ultimately fails. Patterns containing nested quantifiers — (a+)+, (a|a)*, (.*)* — are the usual cause, and the runtime doubles with each additional character, so a 30-character input can take minutes. The defences are to avoid nested quantifiers, to make them possessive or atomic where the engine supports it, or to use a linear-time engine such as RE2 which has no backtracking at all.

Which regex flavour is this?

JavaScript's, as defined by ECMAScript. It supports lookahead, lookbehind, named groups, Unicode property escapes with the u flag and sticky matching with y. It does not support possessive quantifiers, atomic groups, recursion or conditionals, all of which are PCRE features. If your backend uses PCRE, Java or .NET, most everyday patterns behave identically, but anything using those advanced constructs must be tested in the target engine.

How do I match across a newline?

Two separate things are involved. The dot does not match a line terminator unless the s flag is set, so a pattern like a.*b fails across lines while a[\s\S]*b succeeds regardless. Separately, the anchors ^ and $ match only at the start and end of the whole string unless the m flag is set, in which case they also match at line boundaries. If a multi-line pattern is matching too much or too little, those two flags are where to look first.

Outils associés