Regex Cheat Sheet With Tested Examples (JavaScript Flavour)
Developers · Updated October 2, 2026 · 4 min read
Regular expressions are a compact language for describing text patterns. This cheat sheet covers the syntax you will use daily and a set of patterns that were each run through a JavaScript engine to confirm the result shown. Paste any of them into the regex tester to experiment.
Syntax at a glance
. any character except a line break (with the s flag: any character)
\d \w \s digit, word character [A-Za-z0-9_], whitespace
\D \W \S the opposites
[abc] one of a, b or c [^abc] anything except them
[a-z] a range \b word boundary
^ $ start / end of text (with m flag: of each line)
* + ? 0+, 1+, 0 or 1 {3} {2,} {2,5} exact, at least, range
*? +? lazy versions (match as little as possible)
( ) capture group (?: ) group without capturing
(?<name> ) named group \1 backreference to group 1
a|b alternation
(?= ) (?! ) lookahead / negative lookahead
(?<= ) (?<! ) lookbehind / negative lookbehindFlags: g (all matches), i (ignore case), m (multiline anchors), s (dot matches newlines), u (Unicode), y (sticky).
Tested patterns
US phone numbers \b\d{3}-\d{3}-\d{4}\b
"Call 555-123-4567 or 555-987-6543." → 555-123-4567, 555-987-6543
Hex colours #(?:[0-9a-fA-F]{3}){1,2}\b
"#fff #A1B2C3 #12345" → #fff, #A1B2C3 (5 digits rejected)
ISO date + groups \b(\d{4})-(\d{2})-(\d{2})\b
"Due 2026-10-02." → groups 2026, 10, 02
replace with $3/$2/$1 → 02/10/2026
Price after $ (?<=\$)\d+(?:\.\d{2})?
"Price: $49.99, was $60" → 49.99, 60
URLs \bhttps?:\/\/[^\s)]+
"See https://example.com/a?b=1 (and http://x.org)." → both URLs, without the “)”
British or US spelling colou?r → color, colour
Collapse spaces replace / {2,}/g with " " "Hello world again" → "Hello world again"
Swap two words (\w+) (\w+) → $2 $1 "aaa bbb" → "bbb aaa"
Uppercase letters, any script \p{Lu} with the u flag "Élan Über" → É, ÜGreedy, lazy and catastrophic
Quantifiers are greedy: <.+> on “<b>bold</b>” matches the whole string, while the lazy <.+?> matches each tag separately. Prefer a negated class when you can — <[^>]+> is both precise and fast.
Nested quantifiers such as (a+)+ or (\w+\s?)+ can take exponential time on input that almost matches, freezing a browser tab or a server thread. This is called catastrophic backtracking, and it has caused real outages. Rewrite with a single quantifier, make alternatives mutually exclusive, and limit input length for user-supplied patterns.
When not to use a regex
- Email validation: a pragmatic pattern catches typos, but the only real test is sending a confirmation email. Fully RFC-compliant email patterns are enormous and still accept addresses that cannot receive mail.
- HTML and XML: use a parser. Nested structures are beyond what a regular expression can match reliably.
- Dates: a pattern can check the shape 2026-02-30, but not that the date exists — parse it with a date library.
- Numbers with ranges: matching 0–255 is possible but unreadable; capture digits and compare numerically.
Porting between languages
- Escaping: in Java, C# and many other languages, write every backslash twice inside a normal string literal (“\\d+”); in Python use raw strings (r"\d+").
- Named groups are (?<name>…) in JavaScript, Java and .NET, and (?P<name>…) in Python.
- Go’s RE2 engine has no lookarounds or backreferences, by design, which guarantees linear-time matching.
- PHP’s preg functions take delimiters around the pattern: /\d+/i.
Unicode-aware patterns
In JavaScript, \w and \b only understand ASCII letters, so \w+ splits “café” into “caf” and leaves out é. With the u flag you can use Unicode property escapes instead: \p{L} matches a letter in any script, \p{Lu} an uppercase letter, \p{N} a number and \p{Script=Han} a Chinese character. [\p{L}\p{N}]+ is a script-independent replacement for \w+.
Writing patterns others can maintain
- Anchor validation patterns with ^ and $ so they match the whole value, not just part of it.
- Prefer specific classes over .* — [^,]* stops at the next comma instead of backtracking through the whole line.
- Use named groups for anything you read later: (?<year>\d{4}) documents itself.
- Keep a few test strings next to each pattern — the ones it must match and the ones it must not — and run them whenever the pattern changes.
- Split very long patterns into parts built in code, with comments, rather than one unreadable line.
Flags and lookarounds in practice
- g: without it, String.replace changes only the first match — "a-b-c".replace(/-/, "+") gives "a+b-c"; with /-/g it gives "a+b+c".
- m: ^ERROR matches only at the very start of a log; with m it matches at the start of every line.
- s: by default . stops at line breaks, so <p>.*</p> fails across lines; with s it spans them.
- Lookahead: \d+(?= dollars) matches the number in “20 dollars” without including the word.
- Negative lookahead: ^(?!.*password).*$ matches lines that do not contain “password”.
- Lookbehind: (?<=@)\w+ matches the user-name part after an @ without including the @ itself.
The find-and-replace tool runs these patterns over a whole document, with $1-style replacements and a live match count.
Handy find-and-replace recipes
Trim trailing spaces (m flag) find [ \t]+$ replace (nothing)
Collapse blank lines find \n{3,} replace \n\n
CSV to tab-separated (simple) find , replace \t
Wrap each line in quotes (m) find ^(.*)$ replace "$1"
ISO date to US date find (\d{4})-(\d{2})-(\d{2}) replace $2/$3/$1
Remove HTML tags (rough) find <[^>]+> replace (nothing)The CSV recipe only works when no field contains a comma; for real CSV, use a parser such as the CSV to JSON converter. The tag-stripping pattern is fine for quick clean-ups but not a safe way to sanitise HTML.