Test regular expressions against your own text with live match highlighting, capture groups, and a regex replace preview — all computed instantly in your browser.
A regular expression (regex) is a sequence of characters that defines a search pattern, used to match, locate, and manipulate text according to rules far more flexible than a plain substring search. Where a simple search looks for an exact sequence of characters, a regex can express concepts like 'one or more digits,' 'any character except a newline,' 'this word, but only at the start of a line,' or 'an optional group that may or may not appear' — all in a compact, standardized syntax supported (with minor variations) across nearly every programming language.
This tool uses JavaScript's native RegExp engine, the same one that powers pattern matching in every browser and in Node.js, so any pattern that works here will behave identically inside real JavaScript or TypeScript code using new RegExp() or a /pattern/flags literal.
Flags modify how a regular expression's engine interprets and applies the pattern, without changing the pattern itself. The g (global) flag is arguably the most consequential for everyday use: without it, matching stops after the very first match is found anywhere in the string, which is rarely what you want when scanning a document or log file for every occurrence of something.
The i (ignore case) flag is essential whenever input casing can't be guaranteed to be consistent — user-typed text, for instance, rarely follows a predictable case convention. The m (multiline) and s (dotAll) flags both change how patterns interact with line breaks, but in opposite ways: m expands where ^ and $ anchor (to every line, not just the whole string), while s expands what . is allowed to match (including newlines, which it normally excludes). The u (unicode) flag ensures characters are interpreted by their full Unicode code point rather than by UTF-16 code unit, which matters specifically for characters (including many emoji and rare CJK characters) that are represented internally as a pair of code units — without it, a pattern can accidentally split such a character in half.
Parentheses in a pattern create a capture group — a sub-match within the overall match that can be extracted separately. Groups are numbered left to right by their opening parenthesis, starting at 1 (group 0, implicitly, is the entire match). This numbering can get unwieldy fast in a pattern with many groups, which is exactly the problem named capture groups solve: writing (?<year>\d{4}) instead of a bare (\d{4}) lets you reference and display that group by the meaningful name year rather than by remembering it's specifically the third group in a complex pattern.
Both kinds of groups are available for reuse inside a replacement string in Replace mode ($1, $2, ... for numbered groups, $<name> for named ones), and both are exposed programmatically in real JavaScript code through a match object's array-index access (for numbered groups) and its .groups property (for named ones). Non-capturing groups, written (?:...), let you group parts of a pattern for the purposes of applying a quantifier or alternation without creating an extra numbered group — useful for keeping group numbering predictable in longer patterns.
Catastrophic backtracking is the most serious practical pitfall: certain pattern shapes, particularly nested quantifiers like (a+)+ applied against a string that almost — but doesn't quite — match, can cause the regex engine's search to grow exponentially slower with input length, effectively freezing the page or process. Patterns built from user-supplied input, or applied to untrusted or unusually long text, deserve extra scrutiny for this risk.
Greedy versus lazy quantifiers is another frequent source of surprising results: by default, .* is greedy and consumes as much text as possible before backtracking to satisfy the rest of the pattern, which can cause a pattern intended to match 'the shortest possible quoted string' to instead swallow far more text than expected, from the first quote all the way to the last quote in the string. Adding a ? after a quantifier (.*?) makes it lazy instead, matching as little as possible — often the fix for exactly this kind of over-matching. Forgetting to escape regex metacharacters that should be literal (., *, +, ?, (, ), [, ], {, }, ^, $, |, \) is the other classic mistake, especially when a pattern is built dynamically by inserting user-provided text directly into a regex without escaping it first.
Regex Tester validates and previews pattern matching against your own text. These related developer tools handle other text-processing tasks you'll often reach for alongside regular expressions.