JSON Formatter
Pretty-print, validate and minify JSON with precise error positions.
Developer & Security
Test patterns live with match highlighting and a capture group table.
| Flag | Name | Effect |
|---|---|---|
| g | global | Find every match, not just the first |
| i | ignore case | Match regardless of capitalization |
| m | multiline | ^ and $ match at each line break, not just string start and end |
| s | dotAll | . also matches newline characters |
| u | unicode | Correct handling of astral characters and \p{...} property escapes |
| y | sticky | Match only at the exact lastIndex position |
| d | indices | Report start and end offsets for each capture group |
The one that surprises people is m. Without it, ^ matches only the very start of the input, so a pattern intended to match the beginning of every line silently matches once. With m, it matches after every newline — which is what you almost always meant.
A greedy quantifier — *, +, {2,} — consumes as much as possible, then backtracks until the rest of the pattern can match. A lazy one — *?, +? — consumes as little as possible and expands only as needed.
The classic demonstration is HTML tags. Against <b>bold</b>, the pattern <.*> matches the entire string, because .* grabs everything and then backtracks to the last >. The pattern <.*?> matches just <b>.
Most extraction bugs come from a greedy quantifier swallowing past the intended boundary. When a match is longer than expected, adding ? after the quantifier is the first thing to try.
A capture group with a label instead of just a number. Write (?<year>\d{4}) and the match exposes groups.year rather than [1].
The benefit is maintainability. A pattern with six numbered groups becomes unreadable, and inserting a group at the front renumbers everything after it — silently breaking whatever consumed the old indices.
They also work in replacements: $<year>-$<month> is far clearer than $1-$2. Named groups are supported in every current browser, in Python, in .NET, in PCRE and in Java. This tool shows both the number and the name for every group.
A pattern that takes exponential time on certain inputs, hanging the thread it runs on. It is a real denial-of-service vector — ReDoS — and it has taken down production systems including a well-publicized Cloudflare outage in 2019.
It happens when nested quantifiers create multiple ways to match the same text. The pattern (a+)+$ against a long string of "a" characters followed by a "b" forces the engine to try every possible partition before concluding there is no match. Thirty characters can mean over a billion attempts.
The signs to look for are a quantifier applied to a group that itself contains a quantifier, and alternations where the branches can match the same input. Rewriting (a+)+ as a+ fixes the example without changing what it matches. This tool runs matching with a timeout so a pathological pattern reports a warning rather than freezing the page.
JavaScript, specifically the ECMAScript 2018+ engine built into your browser. It differs from PCRE, Python re and .NET in a few areas — lookbehind support, some property escapes, and possessive quantifiers, which JavaScript lacks.
Escape it as \. — an unescaped dot matches any character except a newline.
The g flag is missing. Without it the engine stops at the first match.
Use the s flag so . also matches newlines, and the m flag if you need ^ and $ to anchor to line boundaries.
For a narrow, known-shape extraction, sometimes. For general parsing, no — HTML is not a regular language, and nesting cannot be expressed in a regular expression. Use DOMParser.
A zero-width assertion that checks what follows without consuming it. (?=...) requires a match ahead; (?!...) requires no match. Useful for password rules and for matching a position rather than text.
No. Matching uses the browser native RegExp engine on this page.