Regex Tester & Regular Expression Validator
Type a pattern between the / / delimiters and every match highlights in place as you write: the g i m s u y flags sit on toggles, each hit is listed with its numbered and named capture groups, and the String.replace output is ready to copy.
Replacement follows JavaScript String.replace semantics: $& is the whole match, $1…$99 are numbered groups and $<name> is a named group. A special sequence such as $$ is resolved by the engine into one literal $. The replacement is always plain text, never HTML.
Matches
| # | Index | Matched text | Capture groups |
|---|
Regular expression cheat sheet
- . \. .*
- A dot matches any single character except a line break; the s flag lets it cross lines too. It is not a literal period, so 1.49 also matches 1x49 — write 1\.49 when you mean a decimal point.
- \b
- A word boundary is a zero-width assertion: it checks a position and consumes nothing. \bcat\b matches cat and cat. but not category. Because the underscore counts as a word character, \bfoo\b will not match inside my_foo — that is the usual reason a boundary seems to stop working.
- \d \w \s
- One-character shorthand classes for digits, word characters and whitespace; the uppercase forms \D \W \S negate them. In JavaScript all three are ASCII-only, so \w never matches a Chinese character or an accented letter. Add the u flag and use \p{L} or \p{Script=Han} for real text.
- ^ $
- Anchors. Without m they refer to the whole subject, so a pattern you debugged line by line somewhere else looks broken here. JavaScript is also stricter than Python in one more way: $ matches only the very end, not the spot before a trailing newline — strip that newline, or add m.
- greedy vs lazy
- Quantifiers are greedy: .* eats as much as still lets the rest of the pattern match, which is why "<.*>" on a<b>c<d>e swallows both tags. A trailing ? makes it lazy — "<.*?>" stops at the first > — but lazy only means as little as possible, not correct. A negated class such as "<[^>]*>" is usually faster and reads better.
- [ ]
- A character class matches one character out of a set: [abc], [a-z], [^0-9]. Inside the brackets . | ( ) lose their special meaning, - builds a range (put it first or last for a literal hyphen), and only \, ], ^ and - need care. The class is still one character; to repeat it write [0-9]+.
- ( ) (?<name>) (?:)
- Plain parentheses group and capture, numbered by the order of the opening brackets and reachable as $1 in the replacement. (?<year>…) names a group so that $<year> reads better than $2, and (?:…) groups without capturing — the right choice when you only added brackets for an alternation.
- a | b
- Alternation binds more loosely than anything else, so cat|dog food matches either cat or dog food — not cat food. Wrap what you actually mean: (?:cat|dog) food.
- (?=) (?!)
- Lookahead checks what follows without consuming it, the classic way to combine several requirements: (?=.*\d)(?=.*[A-Z])\S{8,} reads as at least one digit, one capital, eight characters long. Current JavaScript engines also support the lookbehinds (?<=…) and (?<!…).
- $& $1 $<name> $$
- In the replacement string $& is the whole match, $1…$99 are numbered groups, $<name> is a named group, and $$ collapses to a single literal $. A token that names a group the pattern does not have is inserted verbatim, and nothing in the replacement is parsed as HTML.
How to use
- Type the expression body into the Pattern field — the surrounding slashes are only shown for readability, so do not type them — then press Load sample for a realistic set of log lines with a pattern that already matches them.
- Flip the g, i, m, s, u and y toggles. Each one shows its letter, and the helper line under the row spells out what the active flags change; your selection is remembered for the next visit.
- Read the Highlighted preview and the ^ line:column ruler below the Test subject, then check the Matches table: one row per hit with its index, matched text and capture groups, where (not matched) marks a group that did not participate.
- Fill in Replacement to see the replaced output, press Escape special characters to quote the metacharacters in your current selection, then Copy the result or Clear to start over.
Frequently asked questions
Why does my regex work here but not in my code?
This page runs the ECMAScript engine already built into your browser, which is not PCRE or Python. Concretely: \d, \w and \s are ASCII-only, so Chinese or accented text needs \p{L} with the u flag; $ matches only the very end, not the position before a trailing newline the way Python does; (?<name>…) and \k<name> are the group syntax, while (?P<name>) from Python is an error here; and a pattern copied with its // delimiters stops matching anything. In Python source, remember the string literal eats backslashes, so use a raw string: r"\d+".
Why does it match nothing?
Three usual causes. First, the flags: without m, ^ and $ only bound the whole subject, so a pattern tested line by line elsewhere fails on a multi-line paste; without g you only ever see one hit. Second, greediness: .* eats as much as still lets the rest match, so "<.*>" on two tags swallows everything between them — use "<.*?>" or, better, "[^>]*". Third, precedence: alternation binds loosest, so cat|dog food matches cat anywhere. When the syntax itself is wrong the status line shows the engine message plus a hint, and a pattern that matches everywhere is capped rather than left to freeze the page.
Is my pattern or text sent anywhere?
No. Matching, highlighting and replacement all happen inside this page using your browser’s own regex engine — there is no runtime dependency and no network call, so you can verify it by disconnecting after the page loads. That makes it safe to test expressions against log files or payloads that contain real addresses and tokens.
Guides
Related tools
JSON Formatter & Validator
Paste JSON to format, minify or validate it, with the exact line and column of any syntax error. Works offline and never uploads your data.
Unix Timestamp Converter
Convert a Unix timestamp to dates across time zones, or a date back to seconds and milliseconds. The assumed unit is always shown. Runs in your browser.
UUID Generator
Make 1 to 1000 UUIDs locally with the browser CSPRNG, including time-ordered v7 per RFC 9562. Copy the list or download a .txt. Nothing leaves your device.