Quick answer
A regex tester runs a regular expression against sample text and shows every match as you type. In Playxoft's free Regex Tester, enter a pattern between the slashes, switch on flags such as g (global) or i (ignore case), and paste your text: matches are highlighted, capture groups are listed, and each part of the pattern is explained in plain English. Patterns run in your browser's JavaScript engine inside a background worker, so nothing is uploaded.
- Live match highlighting
- Plain-English explanation
- Named capture groups
- Replace preview
- Code export in 6 languages
- Backtracking protection
- Shareable links
- Clickable cheat sheet
How to use the Regex Tester
- 1Type your pattern into Regular expression, between the slashes. Syntax errors are underlined at their exact position, with a hint on how to fix them.
- 2Turn on flags with the chips below the pattern: g finds every match, i ignores case and m makes ^ and $ work on each line.
- 3Paste text into Test string. Matches are highlighted as you type; click inside one to color its capture groups.
- 4Read Explanation to see what every token does, and hover a row to highlight that part of the pattern.
- 5Switch to Replace to preview $1 or $<name> substitutions, or to Code to copy the pattern for JavaScript, Python, Go, C#, PHP or Dart.
- 6Click the link icon to copy a share link with your pattern, flags and test text.
What is a regular expression?
A regular expression (regex) is a pattern that describes a set of strings. Engines use it to find, validate, split and replace text: checking that an input looks like an email address, pulling every date out of a log file, or renaming variables across a codebase. Most characters match themselves; a handful of metacharacters carry the power:
| Token | Meaning | Example |
|---|---|---|
. | Any character except a line break | c.t matches cat, cot, c7t |
\d \w \s | Digit, word character, whitespace | \d{4} matches 2026 |
[abc] [^abc] | One of, or none of, these characters | [aeiou] matches any vowel |
^ $ | Start and end of the string (or line, with m) | ^Hello |
\b | Word boundary | \bcat\b skips concatenate |
* + ? | Zero or more, one or more, optional | colou?r |
{n,m} | Between n and m times | \d{2,4} |
(…) (?:…) | Capturing and non-capturing group | (\d+)px |
(?<name>…) | Named capture group | (?<year>\d{4}) |
The pipe means "or": cat|dog matches either word. To match a metacharacter literally, escape it with a backslash, as in \. or \(. Not sure what a pattern you found online does? Paste it above and the Explanation panel breaks it down token by token. For ready-made, tested patterns, browse the regex pattern library.
What do the regex flags g, i, m, s, u, y, d and v do?
Flags change how the whole pattern behaves. JavaScript supports eight:
| Flag | Name | What it does |
|---|---|---|
g | global | Find every match, not just the first. Required by matchAll() and replaceAll() |
i | ignoreCase | /abc/i also matches ABC |
m | multiline | ^ and $ match at every line break, not only at the ends of the string |
s | dotAll | . also matches line breaks |
u | unicode | Code-point matching, \p{…} property escapes and strict syntax |
y | sticky | Match only at lastIndex, never further along |
d | hasIndices | Record start and end positions of every group in match.indices |
v | unicodeSets | The successor to u: set operations like [\p{L}--[a-z]] and emoji properties |
The most common bug is a missing g: without it, replace() only changes the first occurrence. The second most common is m: if you test one value per line, ^ and $ need it to anchor each line. The v flag (ES2024) cannot be combined with u.
What is the difference between greedy and lazy quantifiers?
Quantifiers are greedy by default: *, +, ? and {n,m} take as much text as they can, then give characters back one at a time if the rest of the pattern fails. Adding ? makes them lazy: they take as little as possible and only grow when they must.
Against the text <b>bold</b>:
<.+>(greedy) matches the whole string<b>bold</b>, because.+runs to the end and backs off only to the last>.<.+?>(lazy) matches<b>and then</b>, stopping at the first>each time.
Often the best fix is neither: <[^>]+> says exactly what is allowed between the brackets, needs no backtracking, and reads more clearly. Lazy quantifiers do not make a pattern faster by themselves; precise character classes do.
How do lookahead and lookbehind work?
Lookarounds check what is next to the current position without including it in the match. They are zero-width: the engine looks, then carries on from where it was.
| Syntax | Name | Succeeds when the text… |
|---|---|---|
(?=…) | Lookahead | after this point matches |
(?!…) | Negative lookahead | after this point does not match |
(?<=…) | Lookbehind | before this point matches |
(?<!…) | Negative lookbehind | before this point does not match |
\d+(?=px) finds the 12 in 12px but not in 12em. (?<=\$)\d+ finds the 42 in $42 without the dollar sign. Several lookaheads at the start of a pattern check independent rules, which is how password policies are usually written: ^(?=.*\d)(?=.*[A-Z]).{12,}$.
JavaScript allows lookbehinds of any length. Python's built-in re requires fixed-width lookbehinds, and Go's RE2 has no lookarounds at all; the Code tab warns you when a pattern will not port.
What is catastrophic backtracking and how do I avoid it?
Most regex engines, including JavaScript's, are backtracking engines: when part of a pattern fails, they go back and try another way to match the earlier parts. If a pattern offers exponentially many ways to split the same text, a failing match tries them all. ^(a+)+$ on thirty a's followed by a ! takes over a billion steps, and the page freezes. On a server, the same mistake is a denial-of-service hole known as ReDoS.
This tester runs every pattern in a Web Worker and stops it after 300 milliseconds, so a runaway pattern shows a warning instead of locking your browser. The Explanation panel also flags risky shapes before you hit them. To avoid the problem:
- No nested quantifiers on the same text:
(a+)+,(\w+\s?)*and(.*)*are the classic offenders. - Make alternatives mutually exclusive:
(a|ab)*can become(ab?)*. - Prefer specific classes to
.*:"[^"]*"instead of".*". - Anchor and bound what you can:
^…$, and limits like{1,64}on untrusted input. - Cap input length before matching, and on servers use an engine or option with a guarantee: Go's RE2 runs in linear time, and .NET supports match timeouts.
How do regex engines differ between JavaScript, PCRE, Python, Go and .NET?
The core syntax is shared, but the details that break ported patterns are not:
| Feature | JavaScript | PCRE (PHP) | Python re | Go (RE2) | .NET |
|---|---|---|---|---|---|
| Lookahead | Yes | Yes | Yes | No | Yes |
| Lookbehind | Any length | Fixed or bounded length | Fixed width | No | Any length |
| Backreferences | Yes | Yes | Yes | No | Yes |
| Named group | (?<n>…) | (?<n>…) | (?P<n>…) | (?P<n>…), or (?<n>…) from Go 1.22 | (?<n>…) |
| Atomic groups | No | Yes | Yes (3.11+) | Not needed | Yes |
\p{…} properties | With u or v | Yes (u needed beyond Latin-1) | No (regex module) | Yes | Categories and blocks |
\d matches | 0–9 only | 0–9 by default | Any Unicode digit | 0–9 only | Any Unicode digit |
$ before a final newline | No | Yes (unless D) | Yes | No | Yes |
| Linear-time guarantee | No | No | No | Yes | Optional (NonBacktracking) |
The Code tab handles the mechanical part for you: it rewrites named groups for Python and Go, turns $ into \Z or \z where the engines disagree, spells \d and \w as ASCII ranges for Python and .NET, converts escapes like \u{1F600}, maps flags to each language's options, and warns about constructs the target cannot run. To go further, test the translated pattern in that language's own tooling before you ship it.
Frequently asked questions
Last updated by the Playxoft engineering team.