tallge

Reference / Regular expression syntax

Regular expression syntax (JavaScript)

This is the syntax of JavaScript’s RegExp. Most of it is shared with PCRE, Python and Java; the differences that bite are noted where they apply.

Characters and classes

SyntaxMatches
.any character except line terminators; any character at all with the s flag
\d \DASCII digit 0-9 / anything else
\w \WASCII letter, digit or underscore / anything else
\s \Swhitespace, including Unicode spaces and line breaks / anything else
[abc]one of a, b, c
[^abc]any character except a, b, c, including line breaks
[a-z0-9_-]ranges; a hyphen is literal at the start or end
\p{L} \p{Lu} \p{N}Unicode letter / uppercase letter / number; needs u or v
\p{Script=Greek}characters of one script; needs u or v
\t \n \rtab, line feed, carriage return
\x41 \u0041 \u{1F600}by code; the braced form needs u
\. \* \\a literal dot, asterisk, backslash

Anchors and boundaries

SyntaxMatches
^start of input; start of any line with m
$end of input; end of any line with m
\bbetween a \w and a non-\w character; based on the ASCII \w
\Bany position that is not \b

Quantifiers

GreedyLazyRepeats
**?0 or more
++?1 or more
???0 or 1
{3}{3}?exactly 3
{2,}{2,}?2 or more
{2,5}{2,5}?2 to 5

Greedy quantifiers take as much as they can and give back; lazy ones take as little as possible. On <b>x</b><b>y</b>, <b>.*</b> matches the whole string and <b>.*?</b> matches only the first element. JavaScript has no possessive quantifiers and no atomic groups.

Groups and references

SyntaxMeaning
(abc)capturing group, numbered from 1 by its opening parenthesis
(?:abc)group without capturing
(?<year>\d{4})named group, available as match.groups.year
\1backreference to group 1
\k<year>backreference to a named group
a|balternation; the leftmost alternative that matches wins, not the longest

Lookaround

SyntaxAsserts that what follows or precedes
(?=abc)follows: abc
(?!abc)follows: not abc
(?<=\$)precedes: a dollar sign
(?<!-)precedes: not a minus

Lookaround consumes nothing. \d+(?=px) finds 12 in 12px. JavaScript allows lookbehind of any length, unlike Python and PCRE, which require a fixed or bounded width.

Flags

FlagPropertyEffect
gglobalfind all matches; exec and test advance lastIndex
iignoreCasecase-insensitive; Unicode case folding with u
mmultiline^ and $ match at line breaks
sdotAll. also matches line breaks
uunicodecode points instead of UTF-16 units; enables \p{} and \u{}; stricter syntax
vunicodeSetslike u, plus set operations such as [\p{L}--[a-z]]
ystickymatch only at lastIndex
dhasIndicesadds start and end indices of each group

Replacement patterns

TokenInserts
$1group 1
$<name>a named group
$&the whole match
$`the text before the match
$'the text after the match
$$a literal dollar sign
'2026-10-07'.replace(/(\d+)-(\d+)-(\d+)/, '$3.$2.$1')   // '07.10.2026'
'a-b-c'.replaceAll('-', '$$')                           // 'a$b$c'

Common traps

A global regex keeps state. const re = /a/g; re.test("a"); re.test("a") returns true and then false, because the second call starts at lastIndex 1.

Nested quantifiers such as (a+)+, (\w*)* or (a|a)* can backtrack exponentially when the input almost matches. Rewrite them so that each part of the input can be matched in only one way: a+ instead of (a+)+.

Inside a string literal every backslash must be doubled: new RegExp("\\d+"). To match user input literally, escape it first; RegExp.escape is in recent engines, and elsewhere use s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").

Sources