Regular Expression Explainer

Paste a regex you inherited, found on Stack Overflow or need to review, and read what each part does — as nested English, a token-by-token table and a railroad diagram.

Input

Settings

History

Load from URL

Three ways to read a pattern

The page parses your pattern with regexp-tree + railroad diagrams and presents it three ways:

  1. Code view — the pattern, the meaning of each flag, then an indented explanation that follows the structure of the regex: “Named group ‘user’ (#1): one or more of: word character (letter, digit or _), ‘.’, ‘+’, ‘-’”. Nesting in the explanation mirrors nesting in the pattern, so alternatives inside a group are listed under that group.
  2. Table view — one row per token (^, (?<user>…), +, [\w.+-], {2,} …) with its meaning, which is handy for documentation or code review comments.
  3. Preview — a railroad diagram: the pattern drawn as a track, with branches for alternation, loops for repetition and boxes for groups. Diagrams make optional parts and alternation precedence obvious in a way text rarely does.

A summary lists the flags, the number of capture groups with their names, and the pattern length.

You can paste a JavaScript-style literal such as /^\d{4}-\d{2}$/gm or just the bare pattern. Flags are explained individually: d (match indices), g (global), i (ignore case), m (multiline anchors), s (dot matches newlines), u (Unicode), v (Unicode sets) and y (sticky).

Which regex flavour?

Patterns are read as JavaScript (ECMAScript) regular expressions, which share most syntax with PCRE, Python, Java and .NET: classes, quantifiers, lazy ? suffixes, lookahead, lookbehind, named groups with (?<name>...) and backreferences. After explaining a pattern, the page also asks the browser’s own regex engine to compile it; if that fails, for example because a backreference names a group that does not exist, you get a warning quoting the engine.

Constructs from other flavours are handled honestly. Possessive quantifiers like a++ (PCRE and Java) are explained, with a warning that JavaScript does not support them and a suggested workaround. Python’s (?P<name>...) syntax is not valid in JavaScript; rewrite it as (?<name>...) to have it explained.

The page has no settings. Ctrl/Cmd+Enter re-explains after an edit, Ctrl/Cmd+Shift+C copies the explanation and Ctrl/Cmd+K opens the command palette. Minify (Ctrl/Cmd+Shift+M) is not relevant to a regex.

Reading regexes safely

An explanation tells you what a pattern matches, not how expensive it is. Nested quantifiers such as (a+)+$ explain neatly yet can take exponential time on a long non-matching input — the classic ReDoS problem. When the explanation shows “one or more of” inside another “one or more of” over the same characters, rewrite the pattern before using it on untrusted input.

Escaping is the other frequent trap. In a JavaScript string, "\d" is just d; the pattern needs "\\d" or a regex literal. If the explanation says “Literal text ‘d’” where you expected digits, a lost backslash is the cause. The regex cheat sheet summarises syntax, flags and common patterns.

Examples

ISO date with named groups

Each named group is explained with its alternatives listed underneath, and the summary names year, month and day.

Input
/(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])/
Output
/(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])/

Explanation
  Named group 'year' (#1): exactly 4 of: digit (0–9)
  Literal text '-'
  Named group 'month' (#2):
    One of 2 alternatives:
      1.
        Literal text '0'
        One of: '1' to '9'
      2.
        Literal text '1'
        One of: '0' to '2'
  Literal text '-'
  Named group 'day' (#3):
    One of 3 alternatives:
      1.
        Literal text '0'
        One of: '1' to '9'
      2.
        One of: '1', '2'
        Digit (0–9)
      3.
        Literal text '3'
        One of: '0', '1'
Open this example in the tool

Password rule built from lookaheads

Two positive lookaheads and one negative lookahead each become a readable condition.

Input
^(?=.*[A-Z])(?=.*\d)(?!.*\s).{12,}$
Output
^(?=.*[A-Z])(?=.*\d)(?!.*\s).{12,}$

Explanation
  Start of the string
  Positive lookahead: followed by:
    Zero or more of: any character except line breaks
    One of: 'A' to 'Z'
  Positive lookahead: followed by:
    Zero or more of: any character except line breaks
    Digit (0–9)
  Negative lookahead: not followed by:
    Zero or more of: any character except line breaks
    Whitespace
  12 or more of: any character except line breaks
  End of the string
Open this example in the tool

Price after a dollar sign, global flag

The lookbehind and the optional non-capturing group for cents are spelled out, and the g flag is explained.

Input
/(?<=\$)\d+(?:\.\d{2})?/g
Output
/(?<=\$)\d+(?:\.\d{2})?/g

Flags
  g  Global: find every match, not just the first

Explanation
  Positive lookbehind: preceded by: '$'
  One or more of: digit (0–9)
  Optionally (zero or one) of:
    Group (not captured):
      Literal text '.'
      Exactly 2 of: digit (0–9)
Open this example in the tool

UUID, case-insensitive

Fixed-length character classes show up as “Exactly 8 of” and so on, which makes the version and variant digits easy to spot.

Input
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
Output
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i

Flags
  i  Ignore case: letters match in upper and lower case

Explanation
  Start of the string
  Exactly 8 of: '0' to '9', 'a' to 'f'
  Literal text '-'
  Exactly 4 of: '0' to '9', 'a' to 'f'
  Literal text '-'
  One of: '1' to '5'
  Exactly 3 of: '0' to '9', 'a' to 'f'
  Literal text '-'
  One of: '8', '9', 'a', 'b'
  Exactly 3 of: '0' to '9', 'a' to 'f'
  Literal text '-'
  Exactly 12 of: '0' to '9', 'a' to 'f'
  End of the string
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
The pattern ends too earlyA group (, a character class [ or an escape \ is not closed.Close the group or class, or escape the character if you meant it literally (\(, \[).
Nothing to repeat before '?'A quantifier has nothing in front of it. Python-style named groups (?P<name>...) cause this, as does a stray ? or * at the start.Use (?<name>...) for named groups in JavaScript, or escape the quantifier as \? to match it literally.
Unescaped '/' inside a /…/ literalA slash inside a regex literal ends the literal early, so the rest is read as flags.Escape it as \/, or paste the bare pattern without the surrounding slashes.
Quantifier {3,1} has its numbers out of orderA {min,max} quantifier has the larger number first.Swap the numbers so that min ≤ max.
Unknown flag 'z'The letters after the closing slash include something that is not a JavaScript flag.Use only d, g, i, m, s, u, v and y. Flags like x (extended) exist in other flavours but not in JavaScript.

Frequently asked questions

Which regex flavour does it explain?

JavaScript (ECMAScript). Most syntax is shared with PCRE, Python, Java and .NET; differences such as possessive quantifiers or (?P<name>) are flagged.

Can I test the regex against sample text?

This page explains and diagrams patterns. To check matches, run the pattern in your browser console or test suite with representative inputs.

What is a railroad diagram?

A drawing of the pattern as a track: you can follow any path from left to right, and every path is one way the regex can match.

Does it warn about catastrophic backtracking?

Not automatically. Look for nested quantifiers over the same characters, such as (a+)+, and rewrite them before using the pattern on untrusted input.

Related tools