Logo

MonoCalc

/

Regex Tester

Programming

/

/gm

Uses your browser's JavaScript regex engine. PCRE, Python, Java and .NET differ in places.

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

Running…

Line endings: LF · 76 chars

Running…

#1 year\d — digitdigitexactly 4 times- — "-""-"#2 month0 — "0""0"[1-9] — one of: 1–9one of: 1–91 — "1""1"[0-2] — one of: 0–2one of: 0–2- — "-""-"#3 day0 — "0""0"[1-9] — one of: 1–9one of: 1–9[12] — one of: 1, 2one of: 1, 2\d — digitdigit3 — "3""3"[01] — one of: 0, 1one of: 0, 1

Flags: g (all matches), m (^ and $ per line)

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

In order: 5 parts, one after another.

(?<year>\d{4})

Named capture group "year" (#1).

\d{4}

Exactly 4 times.

\d

A digit 0–9 (ASCII only, even with u).

-

Matches "-" exactly.

(?<month>0[1-9]|1[0-2])

Named capture group "month" (#2).

0[1-9]|1[0-2]

Either of 2 alternatives, tried left to right; the first that leads to a match wins.

0[1-9]

In order: 2 parts, one after another.

0

Matches "0" exactly.

[1-9]

One character from: 1–9.

1-9

Any character from "1" (U+0031) to "9" (U+0039).

1[0-2]

In order: 2 parts, one after another.

1

Matches "1" exactly.

[0-2]

One character from: 0–2.

0-2

Any character from "0" (U+0030) to "2" (U+0032).

-

Matches "-" exactly.

(?<day>0[1-9]|[12]\d|3[01])

Named capture group "day" (#3).

0[1-9]|[12]\d|3[01]

Either of 3 alternatives, tried left to right; the first that leads to a match wins.

0[1-9]

In order: 2 parts, one after another.

0

Matches "0" exactly.

[1-9]

One character from: 1–9.

1-9

Any character from "1" (U+0031) to "9" (U+0039).

[12]\d

In order: 2 parts, one after another.

[12]

One character from: 1, 2.

1

The character "1".

2

The character "2".

\d

A digit 0–9 (ASCII only, even with u).

3[01]

In order: 2 parts, one after another.

3

Matches "3" exactly.

[01]

One character from: 0, 1.

0

The character "0".

1

The character "1".

Left out on purpose: other engines (PCRE, Python re, Java, .NET, Go RE2) would each need their own WASM build.

There's no step-by-step backtracking debugger, because JavaScript engines don't expose match steps.

Generating a regex from examples or AI explanations would need a backend; this page makes no network requests.

About This Tool

Regex Tester – Build, Explain and Debug JavaScript Regular Expressions

A regex tester closes the gap between writing a regular expression and trusting it. You type a pattern, paste some sample text, and see at once what matches, what each capture group grabbed and where. This tester uses your browser's own JavaScript regex engine, so the results are exactly what String.prototype.matchAll, RegExp.prototype.exec and String.prototype.replace will return in your code, with no approximation or emulation.

Live matches, groups and offsets

Every match is highlighted in the editor, and each capture group gets its own colour, which is used for that group everywhere: in the text, in the pattern, in the table headers and in the diagram. The matches table lists each result with its start and end offset, its line and column, and the value of every group. A group that didn't take part in the match shows as "no match", which is different from a group that matched an empty string (""). Offsets count UTF-16 code units, just like match.index, so an emoji counts as two positions. You can copy the matches or export them as CSV.

Understand a pattern before you ship it

Regular expressions are dense, and a pattern you wrote last month can be hard to read today. The tester breaks the pattern into an explanation tree that describes each token in plain English, and draws a railroad diagram: a track that runs from left to right, splits at alternatives, loops back for repetition and boxes each capture group. Hovering a diagram node or an explanation row underlines the matching part of the pattern, so you can see which characters do what. One classic surprise is spelled out: in abc+, the + repeats only the c, not the whole word.

Warnings for common mistakes

Static checks flag patterns that are valid but probably wrong. [A-z] quietly includes six punctuation characters. a{,5} is literal text in JavaScript, not a quantifier. \A and \Z from other engines just match the letters A and Z. A stray | creates an empty alternative that matches nothing at all. Syntax borrowed from Python or PCRE, such as (?P<name>…), inline flags or possessive quantifiers, gets a hint that shows the JavaScript equivalent.

Catastrophic backtracking
Nested repetition such as (a+)+ can take exponential time on text that almost matches. Every pattern here runs in a background Web Worker with a one-second limit, so a runaway pattern is stopped instead of freezing the page.

Replace, test and export

The Replace panel applies a replacement string with JavaScript's own tokens: $& for the whole match, $1 or $<name> for groups, and $` and $' for the text before and after. Each inserted replacement is highlighted. The Tests panel keeps a list of strings that should match, should not match, or should match in full, and runs each one on a fresh regex so a leftover lastIndex can't skew the result. The Code panel produces ready-to-paste JavaScript for the literal, a test, a loop over all matches and a replace call.

Flags at a glance

Toggle g (all matches), i (ignore case), m (per-line anchors), s (dot matches line breaks), u and v (Unicode modes), y (sticky) and d (group indices). The tester checks which newer features your browser supports, such as the v flag, lookbehind, modifier groups like (?i:…) and duplicate group names, and tells you, rather than assuming a browser version.

Private by design

Nothing you type leaves your device. There is no server-side matching, and a share link stores the pattern, flags, text and tests after the # in the URL, a part browsers never send to a server. Because test text can be sensitive, keep in mind that anyone holding the link can read it. If a link is too long, the test text is left out first.

JavaScript only
This tester deliberately supports one flavour. PCRE, Python, Java, .NET and Go differ in details such as how $ treats a final newline and whether \d covers non-ASCII digits, so test a pattern in the engine that will run it.

Frequently Asked Questions

Is the Regex Tester free?

Yes, Regex Tester is totally free :)

Can I use the Regex Tester offline?

Yes, you can install the webapp as PWA.

Is it safe to use Regex Tester?

Yes, any data related to Regex Tester only stored in your browser (if storage required). You can simply clear browser cache to clear all the stored data. We do not store any data on server.

Which regex flavour does this tester use, and how does it differ from Python or PCRE?

It uses your browser's own JavaScript (ECMAScript) engine, so results match what your JavaScript code will do. Unlike PCRE and Python, JavaScript has no possessive quantifiers or atomic groups, no \A or \Z anchors, its $ never matches just before a final newline, and \d and \w are ASCII-only even with the u flag.

What do the g, i, m, s, u, v, y and d flags do?

g finds every match instead of the first, i ignores case, m makes ^ and $ match at each line, and s lets . match line breaks. u matches by code point and enables \p{…}; v does the same plus set operations such as [A--B]; y makes each match start exactly where the last one ended; and d exposes each group's start and end offsets.

Why did the tester stop with "catastrophic backtracking", and how do I fix the pattern?

Patterns with nested repetition, such as (a+)+, can try an exponential number of ways to split text that almost matches. The tester runs every pattern in a Web Worker and stops it after one second so the page stays responsive. Rewrite the pattern so each part of the text can be matched in only one way, for example a+ instead of (a+)+.

What's the difference between "Matches" and "Full match" in the Tests tab?

Matches passes when the pattern is found anywhere in the test string, like re.test(). Full match passes only when the whole string, from the first character to the last, matches the pattern, even if you didn't anchor it with ^ and $.

Is my test text sent anywhere?

No. Matching, replacing and tests all run in your browser, and the page makes no network requests. Share links keep the pattern and text after the # in the URL, which browsers never send to a server, though anyone you give the link to can read it.

Why do match positions differ from what my text editor shows?

Positions count UTF-16 code units, exactly like JavaScript's match.index, so an emoji or other character outside the Basic Multilingual Plane counts as 2. Line and column are 1-based, and the column is counted in code units too.