Skip to main content
AllDevToolsHub

Regex Cheatsheet

Every regex token you need, organised by category, with per-flavor notes for JavaScript, Python, Go (RE2), and PCRE (Perl / PHP). What works where, what breaks, and the catastrophic-backtracking traps to avoid.

Flavor Tags

When a row lists specific flavors, the syntax is supported only in those engines. Rows without tags work everywhere.

JavaScriptPythonGoPCRE

Character Classes

The single-character building blocks. These appear in every regex you write. Watch the Unicode flag and the locale, the meaning of \w and \d shifts under both.

PatternDescriptionFlavors
.Any character except newline (with /s or DOTALL flag: any character including newline).
e.g. a.c matches abc, axc; not a\nc
JavaScriptPythonGoPCRE
\dDigit. ASCII 0-9 by default; in JS with /u and Python with re.UNICODE, includes every Unicode digit.
e.g. \d+ matches 42, 007, ٤٢ (with /u)
Go's regexp uses RE2, \d is always ASCII-only, no Unicode digit support.
JavaScriptPythonGoPCRE
\DNon-digit. Inverse of \d.
JavaScriptPythonGoPCRE
\wWord character: letter, digit, or underscore. ASCII by default; Unicode-aware with /u or re.UNICODE.
e.g. \w+ matches hello_world42
JavaScriptPythonGoPCRE
\WNon-word character. Whitespace and most punctuation.
JavaScriptPythonGoPCRE
\sWhitespace: space, tab, newline, carriage return, form feed, vertical tab.
e.g. split on \s+ for whitespace tokenization
JavaScriptPythonGoPCRE
\SNon-whitespace.
JavaScriptPythonGoPCRE
[abc]Character class: matches a OR b OR c.
e.g. [aeiou] matches any single vowel
JavaScriptPythonGoPCRE
[^abc]Negated character class: any character that is NOT a, b, or c.
Inside [...], ^ negates only when it's the first character. Otherwise it's literal.
JavaScriptPythonGoPCRE
[a-z]Range inside a character class. Combine ranges: [A-Za-z0-9_].
JavaScriptPythonGoPCRE
\p{Letter}Unicode property escape, matches any Unicode letter. Requires /u flag in JS.
e.g. \p{Letter}+ matches café, mañana, привет
Go's RE2 does not support \p{...} except for a fixed set of script names (e.g., \p{Han}).
JavaScriptPythonPCRE
\P{Letter}Negated Unicode property, anything that is NOT a letter.
JavaScriptPythonPCRE

Anchors and Boundaries

Zero-width matches that pin a pattern to a location. Get these wrong and you'll waste hours debugging why your 'whole-string' regex is partial-matching.

PatternDescriptionFlavors
^Start of string (or start of line with /m flag).
e.g. ^Error matches lines that start with 'Error'
JavaScriptPythonGoPCRE
$End of string (or end of line with /m flag).
e.g. .com$ matches strings ending in .com
JavaScriptPythonGoPCRE
\bWord boundary, between a word character and a non-word character.
e.g. \bcat\b matches 'cat' but not 'category' or 'concat'
JavaScriptPythonGoPCRE
\BNon-word-boundary.
JavaScriptPythonGoPCRE
\AAbsolute start of input, ignores /m flag. Use when you need 'start of whole string' even in multiline mode.
Not supported in JavaScript. Equivalent: just use ^ without /m.
PythonGoPCRE
\ZAbsolute end of input (Python: end-of-string-or-just-before-trailing-newline; Go: end of input).
PythonGoPCRE
\zAbsolute end of input, strict, no trailing newline tolerance.
GoPCRE

Quantifiers

How many times the preceding token must match. Greedy by default, lazy with ?, possessive with + (PCRE). Catastrophic backtracking lives here, see the warnings.

PatternDescriptionFlavors
*Zero or more (greedy).
e.g. ab* matches a, ab, abb, abbb
JavaScriptPythonGoPCRE
+One or more (greedy).
e.g. ab+ matches ab, abb, but not a
JavaScriptPythonGoPCRE
?Zero or one (greedy). Also marks a quantifier as lazy when appended to *, +, {n}.
e.g. colou?r matches color and colour
JavaScriptPythonGoPCRE
{n}Exactly n repetitions.
e.g. \d{4} matches exactly 4 digits
JavaScriptPythonGoPCRE
{n,}n or more repetitions.
e.g. \d{2,} matches 2 or more digits
JavaScriptPythonGoPCRE
{n,m}Between n and m repetitions (inclusive).
e.g. \d{2,4} matches 2-4 digits, preferred over .{0,N} for bounded matches
JavaScriptPythonGoPCRE
*?Lazy zero-or-more, matches as few characters as possible.
e.g. <.*?> matches <a> rather than swallowing <a>text</a>
JavaScriptPythonGoPCRE
+?Lazy one-or-more.
JavaScriptPythonGoPCRE
??Lazy zero-or-one.
JavaScriptPythonGoPCRE
*+Possessive zero-or-more, no backtracking. Prevents ReDoS in PCRE.
Go's RE2 is linear-time by construction, so doesn't need possessive quantifiers. JS and Python don't support them.
PCRE
(?>...)Atomic group, pattern inside cannot be backtracked into. Same goal as possessive quantifiers.
PCRE

Groups and References

Grouping with (), capturing into numbered or named slots, and referencing those captures later in the pattern or in replacements.

PatternDescriptionFlavors
(abc)Capturing group, matches abc and stores it in group 1, 2, 3, ... by left-paren order.
e.g. Reference in replacement: $1 (JS, PCRE), \1 (Python, Go)
JavaScriptPythonGoPCRE
(?:abc)Non-capturing group, groups for quantifiers without consuming a group number. Always prefer when you don't need the capture.
e.g. (?:ab)+ matches ab, abab, ababab
JavaScriptPythonGoPCRE
(?<name>abc)Named capture group. Reference by name in backreferences and substitutions.
e.g. (?<year>\d{4})-(?<month>\d{2})
Go uses the syntax (?P<name>...), Python's original convention, also accepted by Go.
JavaScriptPythonPCRE
(?P<name>abc)Python-style named capture. Supported in Python, Go, and PCRE (alongside (?<name>...)).
PythonGoPCRE
\1Backreference to capture group 1 within the same pattern.
e.g. (\w+) \1 matches repeated word: 'the the'
JavaScriptPythonGoPCRE
\k<name>Backreference to named group.
JavaScriptPythonPCRE
$1, $&, $`, $'Replacement-string backreferences: numbered group, whole match, before-match, after-match.
JavaScriptPCRE

Alternation

Branch within a pattern. Watch the precedence, alternation has the lowest binding strength, so anchor your alternatives with a group if you don't want them spreading across the pattern.

PatternDescriptionFlavors
a|bMatch a or b.
e.g. cat|dog matches cat or dog
JavaScriptPythonGoPCRE
(red|blue|green)Alternation grouped so it applies only to the alternatives, not the surrounding context.
e.g. I love (cats|dogs)!, not 'I love cats|dogs!' which would match 'I love cats' or 'dogs!'
This is the single most common alternation bug. Always group alternations unless you specifically want full-pattern alternation.
JavaScriptPythonGoPCRE

Lookarounds

Zero-width assertions that match if the surrounding text satisfies a sub-pattern. Lookaheads are universal; lookbehinds are partially supported.

PatternDescriptionFlavors
(?=abc)Positive lookahead, matches if abc follows the current position, without consuming.
e.g. \d+(?=px) matches numbers followed by 'px'
JavaScriptPythonGoPCRE
(?!abc)Negative lookahead, matches if abc does NOT follow.
e.g. foo(?!bar) matches 'foo' not followed by 'bar'
JavaScriptPythonGoPCRE
(?<=abc)Positive lookbehind, matches if abc precedes the current position.
e.g. (?<=USD)\d+ matches digits after 'USD'
Not supported in Go's RE2 (linear-time engine excludes lookbehind). In JS, requires ES2018+ (Node 10+, all modern browsers).
JavaScriptPythonPCRE
(?<!abc)Negative lookbehind, matches if abc does NOT precede.
JavaScriptPythonPCRE

Flags / Modifiers

Control how the engine interprets the pattern. Set per pattern in JS (/.../flags), passed as an argument in Python (re.IGNORECASE), inline in Go ((?i)pattern), or both inline and external in PCRE.

PatternDescriptionFlavors
iCase-insensitive. ABC matches abc.
e.g. /hello/i in JS, re.IGNORECASE in Python, (?i) inline in Go
JavaScriptPythonGoPCRE
gGlobal, match all occurrences, not just the first.
e.g. JS only. Python uses re.findall() / re.finditer() instead; Go has FindAll* methods.
JavaScript
mMultiline, ^ and $ match line boundaries instead of string boundaries.
e.g. ^Error in /m mode matches 'Error' at any line start
JavaScriptPythonGoPCRE
sDotall / single-line, `.` matches newlines too.
e.g. JS ES2018+, Python re.DOTALL, Go (?s), PCRE /s
JavaScriptPythonGoPCRE
uUnicode mode, full Unicode \d, \w, \p{...}; surrogate pairs treated as single code points.
e.g. Required in JS for \p{Letter} and to match emoji as single characters
JavaScript
ySticky, match only at lastIndex, no scanning forward.
JavaScript
xExtended / verbose, whitespace and # comments in the pattern are ignored, letting you format long regexes readably.
Not supported in JS (use a template-literal builder pattern instead) or Go.
PythonPCRE

Common Escape Sequences

Special characters that need backslashing in a pattern, plus the literal escapes for non-printables.

PatternDescriptionFlavors
\.Literal dot. Without the backslash, . matches any character.
e.g. \d+\.\d+ matches '1.5' but not '15'
JavaScriptPythonGoPCRE
\\Literal backslash. In a string literal you may need \\\\, four backslashes, depending on how the string is parsed.
JavaScriptPythonGoPCRE
\(Literal left parenthesis. Same for ), [, ], {, }, *, +, ?, |, ^, $.
JavaScriptPythonGoPCRE
\n, \r, \tNewline, carriage return, tab.
JavaScriptPythonGoPCRE
\xHHCharacter by 2-digit hex code. \x41 = 'A'.
JavaScriptPythonGoPCRE
\uHHHHCharacter by 4-digit Unicode code point. \u00E9 = 'é'.
JavaScriptPythonPCRE
\u{HHHHHH}Variable-length Unicode escape, handles code points beyond U+FFFF. Requires /u flag in JS.
JavaScriptPCRE

Per-Flavor Engine Notes

JavaScript

ECMAScript spec, backtracking NFA. Implemented natively in V8 (Chrome, Node), JavaScriptCore (Safari), SpiderMonkey (Firefox).

Not Supported
  • Possessive quantifiers (*+, ++, ?+)
  • Atomic groups ((?>...))
  • Extended /x flag
  • \A and \Z (use ^ and $ without /m instead)
Notes
  • Lookbehind requires Node 10+ / Chrome 62+ / Safari 16.4+. Variable-length lookbehind supported.
  • Unicode property escapes \p{...} require the /u flag.
  • The /g flag is stateful via lastIndex, using the same RegExp object in different contexts is a common bug. Prefer String.prototype.matchAll for iteration.
Python

re module (backtracking NFA, similar to PCRE). For PCRE-like features and atomic groups, install the third-party regex module.

Not Supported
  • Atomic groups in stdlib re (use the regex package instead)
  • Possessive quantifiers in stdlib re
Notes
  • Use raw strings for patterns: r'\d+', otherwise Python string escapes fight regex escapes.
  • re.fullmatch() anchors both ends, equivalent to ^pattern$.
  • Unicode is on by default in Python 3. Pass re.ASCII to restrict \w, \d, \s to ASCII.
  • regex module (pip install regex) adds atomic groups, possessive quantifiers, set operations, variable-width lookbehind.
Go

RE2, linear-time, no backtracking. By construction immune to catastrophic backtracking (ReDoS).

Not Supported
  • Backreferences (\1, \k<name>)
  • Lookahead and lookbehind
  • Possessive quantifiers
  • Atomic groups
  • Most \p{...} Unicode categories (limited set of scripts supported)
Notes
  • Trade-off: RE2 gives up backreferences and lookarounds to guarantee linear time. For untrusted regex input (user-supplied patterns), this is the right choice.
  • Named groups use (?P<name>...), the Python convention.
  • Inline flags only: (?i), (?s), (?m) at start of pattern or scoped group.
PCRE

Perl-Compatible Regular Expressions. The reference 'full-power' engine used by Perl, PHP (preg_*), nginx, Apache, git, and many Unix tools (with PCRE2 since 2015).

Notes
  • Most expressive of the four flavors, supports atomic groups, possessive quantifiers, recursion via (?R) and (?N), conditional patterns (?(cond)yes|no).
  • Highest risk of catastrophic backtracking. Use atomic groups and possessive quantifiers proactively when matching user input.
  • PCRE2 (the active line since 2015) has better Unicode handling than the legacy PCRE1. Most modern systems are on PCRE2.

Frequently Asked Questions

What are the differences between regex in JavaScript, Python, Go, and PCRE?+

JavaScript and Python use backtracking engines with similar core syntax (Python is closer to PCRE, supports verbose /x mode, Python-style named groups). Go uses RE2, a linear-time engine that drops backreferences, lookarounds, and atomic groups in exchange for guaranteed performance on adversarial input. PCRE is the most expressive, recursion, conditionals, atomic groups, possessive quantifiers, and powers Perl, PHP, nginx, and most Unix tools. The biggest practical surprises: Go has no lookbehind, JavaScript has no /x flag, and Go uses (?P<name>...) for named groups while modern JS/PCRE use (?<name>...).

What is catastrophic backtracking and how do I avoid it?+

Catastrophic backtracking is when a regex engine explores an exponential number of possible matches before failing, turning a 50ms operation into a 30-second CPU spike. It happens when nested quantifiers can match the same input multiple ways: (a+)+, (a|a)*, (a|aa)+ are classic offenders. Fixes: (1) use atomic groups (?>a+)+ or possessive quantifiers a++ in PCRE; (2) anchor your pattern to prevent overlap with .*?; (3) be specific instead of generic, [^"]+ instead of .+? when matching inside quotes; (4) for untrusted input, use Go (RE2) or a regex linter like RegexBuddy / SafeRegex. Modern V8 has limited safety but still allows catastrophic patterns.

What is the difference between greedy and lazy quantifiers?+

Greedy quantifiers (* + ? {n,m}) match as much as possible. Lazy quantifiers (*? +? ?? {n,m}?) match as little as possible. Classic example: <.+> on '<a>b</a>' matches the entire string greedily; <.+?> matches just '<a>'. Lazy quantifiers still backtrack, they're not 'safe' against catastrophic backtracking. For true non-backtracking matching, use possessive quantifiers (PCRE: *+ ++) or atomic groups ((?>...)). In Go's RE2, the distinction is purely cosmetic because the engine never backtracks anyway.

How do I match Unicode characters in a regex?+

In JavaScript, add the /u flag and use \p{Letter}, \p{Number}, etc., Unicode property escapes. /[a-z]/i won't match 'é'; /\p{Letter}/u will. In Python 3, Unicode is on by default, \w matches accented letters automatically. To restrict to ASCII, pass re.ASCII. In Go (RE2), Unicode property support is limited to script names, \p{Han} works, \p{Letter} does not. In PCRE, use /u flag and \p{...} just like JavaScript. The pitfall everyone hits: writing [a-zA-Z] when you should write \p{Letter}, your regex silently rejects every non-English name in your input.

How do I write a regex that's safe for user input?+

Two layers. First, the pattern: prefer specific character classes ([^,]+ over .+), avoid nested quantifiers, use atomic groups or possessive quantifiers when available, anchor with ^ and $ so the engine doesn't scan the whole string. Second, the engine: untrusted patterns should run in RE2 (Go), Rust's regex crate, or with an explicit timeout (Java's Pattern.matcher().region() with a timeout watchdog). Never compile user-supplied regex against V8 or Python's re without timeouts. For static patterns against user-supplied input, audit with the SafeRegex / rxxr2 linter, or just sanitize input length to a sane maximum before matching.

Related Tools & References

Test patterns from this cheatsheet live, or browse production-ready patterns for common matching jobs.