KKwikfig.

Regex Tester

Test regular expressions live — matches highlighted in your text, capture and named groups listed, flags as toggles, and a syntax cheat-sheet on the page. Runs entirely in your browser — your numbers never leave this device.

Flags
Test text
Highlighted text (2 matches)

abc 123 def 45

Matches and capture groups
#MatchIndexGroups
11234123
2451245

How it works

A match = the leftmost substring the pattern can consume, trying alternatives left to right | With the g flag, matching resumes at the end of the previous match | Group n = the substring consumed by the nth pair of parentheses; (?<name>…) gives that group a name as well as a number
Regex syntax cheat-sheet — the constructs this tester runs
ConstructMeaningExample
.Any character except a line break (any at all with the s flag)a.c matches abc, a c
\d \DA digit / a non-digit\d+ matches 123 in abc 123
\w \WA word character [A-Za-z0-9_] / a non-word character\w+ matches hello_1
\s \SWhitespace / non-whitespace\s+ matches runs of spaces and tabs
[abc]One character from the set[aeiou] matches any vowel
[^abc]One character NOT in the set[^0-9] matches any non-digit
[a-z]One character in the range[a-f0-9] matches one hex digit
*Zero or more of the preceding itema* matches '', a, aaa
+One or more of the preceding item\d+ never matches empty text
?Zero or one — makes the preceding item optionalcolou?r matches color and colour
{n} / {n,} / {n,m}Exactly n / at least n / between n and m repetitions\d{4} matches a 4-digit year
*? +? ??Lazy versions — match as little as possible<.+?> stops at the first >
^ $Start / end of the string (of each line with the m flag)^\d+$ — the whole text is digits
\bA word boundary — between a \w and a \W position\bcat\b does not match inside cats
( … )Capturing group — its substring is reported as a group(\d+)-(\d+) on 2026-11: groups 2026, 11
(?: … )Non-capturing group — groups without reporting(?:ab)+ matches abab, no groups
(?<name> … )Named capturing group(?<year>\d{4}) names the year group
a|bAlternation — match a or bcat|dog matches either word
\.A literal dot (backslash escapes any special character)1\.5 matches 1.5, not 145

A regular expression is a small program for describing text shapes, and the only way to trust one is to run it against real text. Paste a pattern and a test string here and the tester runs the browser's own regex engine as you type: every match is highlighted in place, and a table lists each match with its position and the substrings its capture groups caught. That loop — write, watch, adjust — catches the classic failure modes instantly: the pattern that matches too much, the group that caught the separator along with the value, the anchor that only works with the multiline flag on.

The flags are toggles because they change the language the pattern speaks. Global (g) is the difference between 'the first match' and 'all matches'. Multiline (m) decides whether ^ and $ mean the whole string or each line inside it. Dotall (s) decides whether . crosses line breaks. The cheat-sheet table below the tool is the reference to keep open while you work — character classes, quantifiers, anchors and group syntax, in the exact spellings the engine accepts.

One behaviour worth knowing before it bites: a pattern that can match the empty string (like a*) matches at every position, including the end of the text, and engines step forward one character after an empty match to avoid looping forever. The tester shows those empty matches in its table even though there is nothing to highlight — run a* over 'baa' and you get an empty match at 0, 'aa' at 1, and an empty match at 3. And everything runs locally: test strings are never uploaded.

Worked examples

Finding every number, with positions

Input
Pattern = (\d+), Flags = g, Text = abc 123 def 45
Working
\d+ is greedy: at each start position it consumes every digit it can. The first run starts at index 4 and takes all three digits; the search resumes after it and finds the second run at index 12. Each match's single capture group holds the same digits as the match itself.
Result
2 matches — "123" at index 4 (group 1: 123), "45" at index 12 (group 1: 45)

Named groups pull a date apart

Input
Pattern = (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}), Flags = none, Text = on 2026-11-01 ok
Working
Without the g flag only the first match is returned. The literal dashes must line up exactly, each \d{4} / \d{2} run fills its named group, and the match starts at index 3 where the year begins.
Result
Match "2026-11-01" at index 3 — year: 2026, month: 11, day: 01

Case-insensitive matching with the i flag

Input
Pattern = hello, Flags = i, Text = say HELLO
Working
The i flag folds case for the whole pattern, so the literal lowercase hello matches the uppercase HELLO at index 4. Without the flag the same test returns no matches — flags are part of the pattern's meaning, not a display option.
Result
1 match — "HELLO" at index 4

Frequently asked questions

Why did my pattern match an empty string?

Because quantifiers like * and ? allow zero repetitions, so the pattern can succeed without consuming anything — a* matches at every position, including the end of the text. The tester lists those empty matches in the table (there is nothing to highlight) and steps one character forward after each, which is what every engine does to avoid an infinite loop. If empty matches surprise you, + (one or more) is usually what you meant.

What is the difference between (…), (?:…) and (?<name>…)?

All three group a sub-pattern so a quantifier or alternation applies to the whole thing. A plain ( … ) also captures: its substring is reported as a numbered group. (?: … ) groups without capturing — use it when you need the grouping but not the substring. (?<name> … ) captures and names the group, so results can be read as year, month, day instead of group 1, 2, 3 — the date example above shows all three readings.

Why does ^ not match at the start of line 2?

Without the m flag, ^ and $ anchor to the whole string only (and $ also just before a final newline). Turn on multiline and they anchor to every line start and end inside the text. The same pattern can therefore return one match or fifty depending on a single flag — which is why the flags here are visible toggles, not buried settings.

Greedy vs lazy — why did .+ eat my whole line?

Quantifiers are greedy by default: .+ consumes as much as it can, then gives characters back only if the rest of the pattern fails. In '<b>x</b><i>y</i>', <.+> swallows everything up to the last >. Adding ? makes it lazy — <.+?> stops at the first > instead. The highlight view makes the difference obvious in one glance, which is the fastest way to build intuition for it.

My pattern is valid in Python / PCRE but fails here — why?

Regex dialects differ. This tester runs JavaScript's engine: named groups are (?<name>…), not (?P<name>…); there are no possessive quantifiers or atomic groups; lookbehind exists but must be fixed-length-free in a different way than PCRE. An invalid pattern here returns the engine's own error message rather than throwing — paste it in and the exact complaint appears.

Is the text I test sent anywhere?

No. The engine is the one built into your browser and the test strings never leave the tab — safe for the log excerpts and data samples that regex work usually involves.

Related tools

More in Developer Tools · Browse all tools