Regex Cheat Sheet
Interactive regex reference with anchors, quantifiers, groups, lookahead, and flags. Each pattern has a try-it button for the regex tester.
This interactive regex cheat sheet covers seven categories: anchors, character classes, quantifiers, groups and references, lookahead and lookbehind, flags, and common patterns. Every entry has a description, example, and a try-it button that opens the Regex Tester with the pattern pre-loaded. Use the search box to filter across all categories instantly.
About Regex Cheat Sheet
Anchors
Anchors match positions in the string rather than characters. They are zero-width, meaning they do not consume any input.
| Anchor | Meaning | Example | Matches |
|---|---|---|---|
| ^ | Start of string (or line with m flag) | ^Hello | "Hello world" but not "Say Hello" |
| $ | End of string (or line with m flag) | world$ | "Hello world" but not "world class" |
| \b | Word boundary | \bcat\b | "cat" but not "category" or "scat" |
| \B | Not a word boundary | \Bcat\B | "concatenate" but not "cat" |
Word boundaries (\b) are especially useful for matching whole words. The pattern \b\d{3}\b matches exactly three digits surrounded by non-word characters or string edges, preventing partial matches inside longer numbers.
Character Classes
Character classes match one character from a defined set. Shorthand classes provide convenient aliases for common sets.
| Class | Matches | Equivalent |
|---|---|---|
| \d | Any digit | [0-9] |
| \D | Any non-digit | [^0-9] |
| \w | Word character | [a-zA-Z0-9_] |
| \W | Non-word character | [^a-zA-Z0-9_] |
| \s | Whitespace (space, tab, newline) | [ \t\n\r\f\v] |
| \S | Non-whitespace | [^ \t\n\r\f\v] |
| . | Any character except newline | (all except \n, unless s flag) |
Custom character classes are defined with square brackets. [aeiou] matches any vowel. Ranges like [a-z] match any lowercase letter. A caret at the start negates the class: [^0-9] matches anything that is not a digit.
Quantifiers
Quantifiers specify how many times the preceding element should match. All quantifiers are greedy by default (match as much as possible). Add ? to make them lazy (match as little as possible).
| Quantifier | Meaning | Greedy Example | Lazy Version |
|---|---|---|---|
| * | 0 or more | a* matches "" and "aaa" | a*? |
| + | 1 or more | a+ matches "a" and "aaa" | a+? |
| ? | 0 or 1 (optional) | colou?r matches "color" and "colour" | N/A |
| {n} | Exactly n | \d{3} matches "123" | N/A |
| {n,} | n or more | \d{2,} matches "12" and "12345" | \d{2,}? |
| {n,m} | Between n and m | \d{2,4} matches "12", "123", "1234" | \d{2,4}? |
Groups and References
Groups bundle parts of a pattern together and optionally capture the matched text for later use.
| Syntax | Type | Purpose | Example |
|---|---|---|---|
| (...) | Capturing group | Captures matched text, referenced by index | (\d+)-(\d+) captures both numbers |
| (?:...) | Non-capturing group | Groups without capturing (better performance) | (?:ab)+ matches "ababab" |
| (?<name>...) | Named group | Captures with a readable name | (?<year>\d{4}) |
| \1, \2 | Backreference | Matches same text as a previous group | (\w+)\s+\1 matches "the the" |
| (a|b) | Alternation | Matches either alternative | (cat|dog) matches "cat" or "dog" |
Backreferences are useful for finding duplicated words. The pattern \b(\w+)\s+\1\b matches repeated words like "the the" or "is is". In JavaScript's replace method, captured groups are referenced as $1, $2, etc.
Lookahead and Lookbehind
Lookarounds check what comes before or after a position without including it in the match. They are essential for context-dependent matching.
| Syntax | Name | Matches When | Example |
|---|---|---|---|
| (?=...) | Positive lookahead | What follows matches the pattern | \w+(?=\.) matches "end" in "end." |
| (?!...) | Negative lookahead | What follows does NOT match | foo(?!bar) matches "foo" unless followed by "bar" |
| (?<=...) | Positive lookbehind | What precedes matches the pattern | (?<=\$)\d+ matches "100" in "$100" |
| (?<!...) | Negative lookbehind | What precedes does NOT match | (?<!\$)\d+ matches "100" in "100 items" |
A classic use case is password validation. The pattern (?=.*[A-Z])(?=.*\d).{8,} uses two positive lookaheads to assert that the string contains at least one uppercase letter and one digit, then matches 8 or more characters.
Special Characters That Need Escaping
These characters have special meaning in regex. To match them literally, prefix with a backslash.
| Character | Regex Meaning | Literal Match |
|---|---|---|
| . | Any character | \. |
| * | 0 or more | \* |
| + | 1 or more | \+ |
| ? | Optional | \? |
| ^ | Start of string / negation | \^ |
| $ | End of string | \$ |
| () | Group | \( \) |
| [] | Character class | \[ \] |
| {} | Quantifier | \{ \} |
| | | Alternation | \| |
| \ | Escape | \\ |
Inside a character class [...], most special characters lose their meaning. Only ^, ], \, and - need escaping inside square brackets.
Regex in JavaScript
JavaScript offers two ways to create regex: literal notation (/pattern/flags) and the RegExp constructor (new RegExp("pattern", "flags")). The literal form is more common and avoids double-escaping backslashes.
| Method | Returns | Example |
|---|---|---|
| test() | Boolean (match found?) | /\d+/.test("abc123") returns true |
| exec() | Match array or null | /(\d+)/.exec("abc123") returns ["123", "123"] |
| match() | All matches (with g) or first match | "abc123def456".match(/\d+/g) returns ["123", "456"] |
| matchAll() | Iterator of all matches with groups | Useful for named groups and capture extraction |
| replace() | String with replacements | "hello".replace(/l/g, "r") returns "herro" |
| split() | Array split by pattern | "a, b, c".split(/,\s*/) returns ["a", "b", "c"] |
Performance Tips
| Problem | Cause | Solution |
|---|---|---|
| Catastrophic backtracking | Nested quantifiers like (a+)+ on non-matching input | Use atomic groups (PCRE) or rewrite to avoid nesting |
| Slow on large input | Complex pattern tested against megabytes of text | Anchor the pattern, use character classes instead of .* |
| Recompilation | Creating new RegExp inside a loop | Compile once outside the loop, reuse the object |
| Unnecessary captures | Every () creates a capture group | Use (?:) for groups you do not need to extract |
Catastrophic backtracking is the most dangerous performance issue. The pattern (a+)+ against the input "aaaaaaaaaaab" forces the engine to try exponentially many combinations before failing. OWASP classifies this class of bug as a Regular Expression Denial of Service (ReDoS) vulnerability and lists it among the top application-layer DoS vectors reported in the wild. Always test complex patterns against non-matching input of the form "aaaaaa...aaab" to check for backtracking before shipping them.
How Regex Flavours Differ
The same pattern can behave differently across languages because regex engines do not share a single specification. JavaScript follows ECMA-262 Annex B, Python uses the `re` module (with a separate `regex` package for PCRE-like features), Java uses `java.util.regex`, and most Linux command-line tools use POSIX BRE or ERE. Knowing which features are portable saves hours of debugging when moving a pattern between stacks.
| Feature | JavaScript | Python (re) | PCRE / PHP | POSIX (grep, sed) |
|---|---|---|---|---|
| Lookbehind | Yes (ES2018+) | Fixed-width only | Yes, variable-width in PCRE2 | No |
| Named groups | (?<name>...) | (?P<name>...) | Both syntaxes | No |
| Unicode property \p{L} | Requires u flag | Requires `regex` package | Yes | No |
| Atomic groups (?>...) | No | Python 3.11+ | Yes | No |
| Possessive quantifiers *+ | No | Python 3.11+ | Yes | No |
| Recursion / subroutines | No | Only via `regex` | Yes | No |
If a pattern has to run in both browser and Python, stick to features in the intersection: basic classes, quantifiers, capturing and non-capturing groups, alternation, anchors, and fixed-width lookbehinds. Save atomic groups and recursion for server-side code where you control the engine.
Worked Example: Extracting UK Postcodes
UK postcodes follow a well-defined format documented by Royal Mail and reproduced in the ONS Postcode Directory. The full grammar has several area-letter exceptions, but a practical pattern that matches 99% of real postcodes is `\b[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}\b` with the case-insensitive flag.
Worked example: Against the text "Write to SW1A 1AA or M1 1AE for samples", the engine first looks for a word boundary, then consumes one or two uppercase letters (SW), one digit (1), an optional letter or digit (A), an optional space, one digit (1), two uppercase letters (AA), then another word boundary. It matches "SW1A 1AA" and continues scanning to find "M1 1AE". Both matches are returned. The same pattern rejects "SW1A1AA0" because the trailing 0 breaks the word boundary requirement.
This is a good illustration of three principles: use \b anchors to stop mid-word matches, use ? for truly optional characters (the second character of the outward code), and test both formats you expect (SW1A 1AA and M1 1AE) before trusting the pattern.
Common Mistakes That Cost Hours
The most common regex bugs in production code share a few patterns. Avoiding them removes a surprising amount of debugging time.
| Mistake | Why It Breaks | Fix |
|---|---|---|
| Using .* to match anything between quotes | Greedy matching consumes the closing quote and keeps going | Use .*? (lazy) or a negated class [^"]* |
| Forgetting to escape the dot in domain names | "example.com" matches "exampleXcom" too | Always use \. for literal dots |
| Regex for HTML parsing | HTML is not regular - nested tags are impossible to parse reliably | Use a DOM parser; reserve regex for trivial extraction |
| Testing email validity with a long regex | RFC 5322 allows far more than most patterns accept | Check for an @ and a dot, then send a confirmation email |
| Forgetting the g flag in replace() | Only the first occurrence is replaced | Use /pattern/g or String.replaceAll() |
| Using $ instead of end-of-input | With the m flag, $ matches end of line, not string | Use \z in Python/PCRE, or drop the m flag in JS |
On email in particular, Jeff Atwood has pointed out that the canonical RFC 5322-compliant regex is over 6,000 characters long and still rejects some valid addresses. The practical answer is almost always: a short sanity check, then an email round-trip to the address. For a cleaner slug-safe string, the Slug Generator handles case and punctuation without any regex at all.
Safe Alternatives to Dangerous Patterns
If you care about catastrophic backtracking, three defensive techniques matter. First, avoid nested quantifiers: instead of (a+)+, write a+ which matches the same text without the exponential worst case. Second, anchor the pattern: `^\d+$` has one path to a failure; `\d+` inside a longer pattern does not. Third, prefer character classes over alternation where possible - [abc] is always faster than (a|b|c) because the engine can check membership in constant time rather than trying each branch.
Modern engines are adding safety nets. Google's RE2 library (used in Go's standard library and in Cloudflare Workers) guarantees linear-time matching by refusing to support backreferences and lookarounds, which are the features that introduce exponential worst cases. Rust's `regex` crate uses the same approach. When building server-side code that accepts user-supplied patterns, an RE2-based engine is safer than PCRE.
Testing and Debugging Workflow
A reliable workflow for any non-trivial pattern has four steps. Write the pattern against a small test string you control. Paste a real-world sample and check matches. Paste a deliberately adversarial input (empty string, very long repetitions of one character, the pattern's own metacharacters as literal text) to see if it crashes or hangs. Then put it in production behind a timeout, even if you trust it.
To test patterns live with highlighted matches, open the Regex Tester. For plain text search and replace without writing a pattern by hand, the Find and Replace tool is simpler. Everything runs in your browser.
Sources
Frequently Asked Questions
What regex categories are covered?
Seven categories: anchors, character classes, quantifiers, groups and references, lookahead and lookbehind, flags, and common patterns. Each category lists the most useful patterns with descriptions and examples.
What does the Try It button do?
It opens the regex tester tool in a new tab with the pattern and example text pre-filled so you can see the matches highlighted and experiment with modifications.
Can I search for a specific pattern?
Yes. Use the search box to filter across all categories by pattern syntax, description, or example text. Only matching entries are shown.
Does this cover all regex flavours?
The patterns listed are compatible with JavaScript regex and cover the most commonly used syntax. Most will work in Python, Java, and other languages too, though some advanced features like lookbehind have varying support.
Are the common patterns production-ready?
The common patterns section shows simplified versions for quick reference. For production use, you will likely need more thorough validation, especially for emails and URLs where edge cases are numerous.
Related Tools
Link to this tool
Copy this HTML to link to this tool from your website or blog.
<a href="https://toolboxkit.io/tools/regex-cheat-sheet/" title="Regex Cheat Sheet - Free Online Tool">Try Regex Cheat Sheet on ToolboxKit.io</a>