Regex Tester
Free online regex tester with live matching, named capture groups, lookahead/lookbehind, and a replace/substitution mode using $1 and $
Regex Tester - Test and Debug Regular Expressions Online
A powerful online regular expression tester that helps you test, debug, and learn regex patterns. Features real-time matching with syntax highlighting, capture group display, all JavaScript regex flags support, and detailed match information. Perfect for developers and anyone working with pattern matching.
What is a regular expression and what is it used for?
A regular expression (regex or regexp) is a sequence of characters that defines a search pattern, used for string matching, validation, extraction, and substitution. The concept was formalized by Stephen Kleene in the 1950s and made practical by Ken Thompson's grep in 1968. Modern regex engines power input validation (emails, phone numbers, ZIP codes), log parsing, find-and-replace in editors, URL routing in web frameworks, and lexical analysis in compilers. Every major language ships a regex engine: JavaScript's RegExp, Python's re, Java's Pattern, .NET's Regex, and PCRE in PHP. While syntax varies between flavors (POSIX BRE, ERE, PCRE, RE2, ECMAScript), the core building blocks — character classes, quantifiers, anchors, groups, and alternation — are universal.
What is the difference between greedy, lazy, and possessive quantifiers?
By default, quantifiers like *, +, ?, and {n,m} are greedy: they match as much as possible while still allowing the overall pattern to succeed. The pattern <.+> against <b>bold</b> matches the entire string, not just <b>, because + consumes everything up to the final >. Lazy (non-greedy) quantifiers add ? — so <.+?> matches just <b>, then <b>, taking the smallest substring that works. Possessive quantifiers add + (++, *+, ?+) and never backtrack once matched, which improves performance and prevents catastrophic backtracking but can cause matches to fail where greedy would succeed. PCRE, Java, and Ruby support possessive; JavaScript and Python do not (use atomic groups (?>...) where available).
What are anchors, lookahead, and lookbehind?
Anchors match positions, not characters. ^ matches the start of input (or line in multiline mode), $ matches the end, \b matches a word boundary, and \A / \Z match absolute start / end regardless of multiline. Lookahead (?=...) and negative lookahead (?!...) assert what follows the current position without consuming it: q(?=u) matches q only when followed by u. Lookbehind (?<=...) and (?<!...) assert what precedes: (?<=\$)\d+ matches a number preceded by a dollar sign. JavaScript gained lookbehind in ES2018; older browsers and RE2 (used by Go and Cloudflare) do not support it. Lookarounds are zero-width: they affect matching but contribute no characters to the result.
How do capturing groups, non-capturing groups, and named groups differ?
Parentheses (abc) create a capturing group that both groups expressions for quantifiers and saves the matched substring for backreferences (\1) or extraction. Non-capturing groups (?:abc) group without saving, which is faster and avoids cluttering the match array — use them whenever you only need grouping. Named groups (?<name>abc) (PCRE/Python/.NET/ES2018+) save under a readable name accessible via match.groups.name, making patterns self-documenting. A regex like (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) parses an ISO date into labeled fields. Backreferences \k<name> or \1 let you match the same text again — useful for finding repeated words like \b(\w+)\s+\1\b which catches duplicate words.
How do I test a regex replacement / substitution with $1 and named groups?
Enable the Replace / Substitution mode, then type a replacement string that references your captured text with tokens. In JavaScript's String.replace (which this tool uses), $1, $2, $3 insert positional capture groups, $<name> inserts a named group, $& inserts the whole match, $` inserts everything before the match, and $' inserts everything after it. For example, pattern (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) with replacement $<day>/$<month>/$<year> rewrites 2026-05-29 into 29/05/2026 — the classic ISO-to-DMY date reformat. Without the global g flag, only the FIRST match is replaced (native behavior); add g to replace every occurrence. This mirrors sed s/old/new/g, editor find-and-replace, and log-rewriting workflows, so you can author and verify the substitution here before pasting it into your codebase.

What are common flags (g, i, m, s, u, y) and what do they do?
Flags modify regex behavior globally. g (global) returns all matches instead of just the first, required for replaceAll-style operations in JavaScript. i (case-insensitive) makes [A-Z] match a-z too. m (multiline) changes ^ and $ to match line boundaries, not just string boundaries. s (dotall, ES2018+) lets . match newlines, otherwise excluded. u (unicode) enables full Unicode mode with surrogate pair handling and \p{Script=Latin}-style property escapes. y (sticky) anchors the match at lastIndex, useful for tokenizers. Python uses re.IGNORECASE, re.MULTILINE, re.DOTALL constants instead of flag letters. Combine flags as needed: /pattern/gim or (?gim) inline.
Why do some regexes hang the browser? (catastrophic backtracking)
Catastrophic backtracking happens when a regex tries exponentially many ways to match before giving up. The classic example is (a+)+b against aaaaaaaaaaaaaaaaaaaa (no b): the engine tries every partition of the a's between the inner and outer +, which is 2^n attempts. ReDoS (Regular expression Denial of Service) attacks weaponize this — a single malicious input can freeze a server for minutes. OWASP's ReDoS guidance recommends: avoid nested quantifiers ((a+)+, (a*)*), avoid overlapping alternation ((a|a)+), prefer atomic groups (?>a+)+ or possessive quantifiers a++, and use linear-time engines like RE2 (Go, Cloudflare) or Rust's regex crate for untrusted input. Test patterns with tools like regex101's debugger or the regexploit linter before shipping.
What are the differences between POSIX BRE, ERE, PCRE, and RE2?
POSIX BRE (Basic Regular Expressions, used by sed and grep) requires backslashes before metacharacters: \(group\), \{2,3\}, \+ is literal. POSIX ERE (Extended, used by egrep, awk) treats those characters as special by default — closer to modern syntax. PCRE (Perl-Compatible Regular Expressions, used by PHP, NGINX, and many tools) is the de facto modern standard: it supports lookaround, named groups, backreferences, recursion, and conditionals. RE2 (Google, used by Go, Cloudflare, Sourcegraph) deliberately omits backreferences and lookaround to guarantee linear-time matching, eliminating ReDoS. ECMAScript regex (JavaScript) is close to PCRE but lacks some features (recursion, conditionals) and adds the y flag. Always check the target engine's documentation — a working PCRE pattern may fail in RE2 or grep.
How do I escape special characters and match Unicode properly?
Twelve metacharacters need escaping with a backslash: . ^ $ * + ? ( ) [ ] { } | \. To match a literal dot, use \. inside the pattern. Inside [...] character classes, only ] \ ^ - need escaping, and ^ only when at position 1. For dynamic patterns built from user input, use a library escape function (RegExp.escape proposal, re.escape in Python, preg_quote in PHP) — never concatenate raw input. For Unicode, enable the u flag and use property escapes: \p{L} (any letter), \p{N} (number), \p{Script=Han} (Chinese characters), \p{Emoji}. The deprecated \w only matches ASCII word chars by default — for international names use [\p{L}\p{N}_]. Surrogate pairs (emoji, rare CJK) only work correctly with the u flag in JavaScript.
Key Features
- Test regular expressions with real-time matching
- Syntax highlighting for matches
- Display all capture groups
- Support all JavaScript regex flags (g, i, m, s, u, y)
- Show match count and positions
- Highlight matches in test string
- Detailed error messages for invalid patterns
- Copy and paste functionality
- Upload text files for testing
- Dark mode support
- 100% client-side processing - data never leaves your browser
- Works offline after initial load
- Mobile-friendly responsive design
