Cheat sheet
JavaScript (ECMAScript) regular expression syntax, as supported by current browsers and Node.js. Ready-made patterns ↓
Characters
. | Any character except line breaks (with the s flag: any character) |
\d \D | A digit 0–9 / anything but a digit |
\w \W | A word character [A-Za-z0-9_] / anything else |
\s \S | Whitespace (space, tab, line breaks, Unicode spaces) / anything else |
\t \n \r \v \f | Tab, newline, carriage return, vertical tab, form feed |
\0 | The NUL character |
\xhh | Character by 2-digit hex code, e.g. \x41 is A |
\uhhhh | Character by 4-digit hex code, e.g. é is é |
\u{h…} | Any code point, e.g. \u{1F600} (u or v flag) |
\cX | Control character, e.g. \cJ is a newline |
\. \* \\ \/ | Escape a special character: \ ^ $ . | ? * + ( ) [ ] { } / |
Character classes
[abc] | One of a, b or c |
[^abc] | Any character except a, b or c |
[a-z0-9] | A range: a to z or 0 to 9 |
[\w.-] | Classes can hold escapes; a - at the start or end is literal |
[^] | Any character, including line breaks |
[\b] | A backspace character (only inside a class) |
\p{L} \p{Lu} | A letter / an uppercase letter, by Unicode property (u or v flag) |
\p{Script=Greek} | A character from a Unicode script (u or v flag) |
\P{…} | A character without the property (u or v flag) |
[\p{L}--[a-z]] | Difference: letters except a–z (v flag) |
[\w&&\p{ASCII}] | Intersection: in both sets (v flag) |
[\q{abc|d}] | A class that also matches whole strings (v flag) |
Anchors and boundaries
^ | Start of the text (with the m flag: start of a line) |
$ | End of the text (with the m flag: end of a line) |
\b | Word boundary: between \w and \W, or at the start or end |
\B | Not a word boundary |
Quantifiers
* | Zero or more times |
+ | One or more times |
? | Optional: zero or one time |
{n} | Exactly n times |
{n,} | n or more times |
{n,m} | Between n and m times |
*? +? ?? {n,m}? | Lazy: as few times as possible (the default is greedy, as many as possible) |
Groups, lookaround and alternation
(…) | Capturing group, numbered from 1 by its opening parenthesis |
(?<name>…) | Named capturing group |
(?:…) | Non-capturing group |
a|b | Alternation: a or b (lowest precedence; group it to limit it) |
(?=…) | Lookahead: followed by … |
(?!…) | Negative lookahead: not followed by … |
(?<=…) | Lookbehind: preceded by … |
(?<!…) | Negative lookbehind: not preceded by … |
(?i:…) (?-i:…) | Turn flags i, m or s on or off inside the group (newer browsers) |
Backreferences
\1 \2 … | The same text that group 1, 2 … matched |
\k<name> | The same text that the named group matched |
Flags
g | global: find all matches, not just the first |
i | ignore case |
m | multiline: ^ and $ match at every line |
s | dotAll: . also matches line breaks |
u | unicode: code points, \p{…}, \u{…}, stricter syntax |
v | unicodeSets: like u, plus set operations and \q{…} (not together with u) |
y | sticky: match only at lastIndex |
d | indices: record start and end of each group (match.indices) |
Replacement string
$1 $2 … | Text of group 1, 2 … |
$<name> | Text of a named group |
$& | The whole match |
$` | The text before the match |
$' | The text after the match |
$$ | A literal $ |
In code
re.test(str) | true if there is a match |
str.match(re) | Without g: the first match with groups. With g: an array of all matched texts |
str.matchAll(re) | Iterator over every match with its groups (needs g) |
re.exec(str) | Next match; with g or y it continues from re.lastIndex |
str.replace(re, s) | Replace the first match, or all with g; s can be a function |
str.replaceAll(re, s) | Replace all matches (needs g) |
str.split(re) | Split at matches; captured groups are included in the result |
new RegExp(src, flags) | Build a regex from a string (escape backslashes in string literals) |
Ready-made patterns
Each one opens in the tester with sample text. They are practical, not perfect validators.
Email address (rough)
Good for finding addresses in text. Real address syntax is far looser; to validate, send an email.
/[\w.+-]+@[\w-]+(?:\.[\w-]+)+/g
IPv4 address
Four numbers 0–255 separated by dots.
/\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b/g
IPv6 address
Full and :: compressed forms, one address per line. No zone IDs or embedded IPv4.
/^(?:(?:[\da-f]{1,4}:){7}[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,7}:|(?:[\da-f]{1,4}:){1,6}:[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,5}(?::[\da-f]{1,4}){1,2}|(?:[\da-f]{1,4}:){1,4}(?::[\da-f]{1,4}){1,3}|(?:[\da-f]{1,4}:){1,3}(?::[\da-f]{1,4}){1,4}|(?:[\da-f]{1,4}:){1,2}(?::[\da-f]{1,4}){1,5}|[\da-f]{1,4}:(?::[\da-f]{1,4}){1,6}|:(?:(?::[\da-f]{1,4}){1,7}|:))$/gim
ISO 8601 date
YYYY-MM-DD with named groups. Does not check the number of days in a month.
/\b(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])\b/g
Time (24-hour)
HH:MM with optional :SS.
/\b(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d)?\b/g
Hex colour
#rgb, #rgba, #rrggbb or #rrggbbaa.
/#(?:[\da-f]{8}|[\da-f]{6}|[\da-f]{3,4})\b/gi
UUID
Any version, either case.
/\b[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12}\b/gi
URL (http and https)
Scheme, host, optional port and the rest up to whitespace. Trailing punctuation after a path is included.
/\bhttps?:\/\/[\w.-]+(?::\d+)?(?:[/?#]\S*)?/gi
MAC address
Six hex pairs with : or -; the backreference \1 makes every separator the same.
/\b[\da-f]{2}([:-])[\da-f]{2}(?:\1[\da-f]{2}){4}\b/gi
Semantic version
The semver.org pattern with named groups, one version per line.
/^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<pre>(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-z-][\da-z-]*))*))?(?:\+(?<build>[\da-z-]+(?:\.[\da-z-]+)*))?$/gim
Croatian OIB
Exactly 11 digits. The last digit is a check digit (ISO 7064, MOD 11,10), which a regex cannot verify.
/\b\d{11}\b/g
Repeated word
A word followed by the same word, using a backreference.
/\b(\w+)\s+\1\b/gi
Trailing whitespace
Spaces and tabs at the end of each line. Replace with nothing to trim.
/[ \t]+$/gm