Regular expressions
Pieces, quantifiers, groups, flags and when not to use regex.
Updated
What a regular expression is
A regular expression (regex) is a pattern that describes what a text looks like: "starts with a capital letter", "contains a phone number", "is a 5-digit ZIP code". With it you can check, search, extract and replace pieces of text.
/^\d{5}$/.test('94103') // true — exactly 5 digits
'Tel: 0722 123 456'.match(/\d+/g) // ['0722', '123', '456']
'a-b-c'.replace(/-/g, ' ') // 'a b c'It looks cryptic at first, but it's just a few pieces combined.
The basic pieces
| Piece | Matches | Example |
|---|---|---|
abc |
exactly that text | /cat/ |
. |
any character (except a newline) | /c.t/ → cat, cut |
\d / \w / \s |
a digit / a letter-digit-underscore / whitespace | /\d\d/ |
[abc] / [a-z] / [^0-9] |
one from the set / a range / anything except | /[aeiou]/ |
^ / $ |
the start / end of the text | /^Hello/ |
\b |
a word boundary | /\bvar\b/ |
\. \? \( |
special characters, as text | /\.js$/ |
Quantifiers — how many times
| Quantifier | Means |
|---|---|
? |
0 or 1 (optional) |
* |
0 or more |
+ |
1 or more |
{3} / {2,4} / {2,} |
exactly 3 / between 2 and 4 / at least 2 |
By default they're greedy (take as much as they can); with a ? after them they become lazy: /<.+?>/ stops at the first >.
Groups
const m = '2026-10-08'.match(/(\d{4})-(\d{2})-(\d{2})/)
m[1] // '2026'
const { groups } = '2026-10-08'.match(/(?<year>\d{4})-(?<month>\d{2})/)
groups.year // '2026' — named groups, more readable
/(?:ab)+/ // a non-capturing group — just to apply + to "ab"
/cat|dog/ // alternationFlags
| Flag | Effect |
|---|---|
g |
all matches, not just the first |
i |
case-insensitive |
m |
^ and $ on every line |
u |
correct Unicode (diacritics, emoji) — use it by default |
The methods — what to use when
| You want | Method |
|---|---|
| yes / no | regex.test(str) |
| the first match + groups | str.match(regex) (without g) |
| all matches with groups | [...str.matchAll(/.../g)] |
| replacing | str.replace(regex, 'x') / replaceAll / with a function: replace(re, m => ...) |
| splitting | str.split(/\s*,\s*/) |
When not to use regex
- A fully correct email — practically impossible; use
type="email"/z.email(). - HTML / JSON — use a parser (
DOMParser,JSON.parse). - URLs —
new URL(). - Huge regexes nobody can read anymore — a few simple checks are better.
Summary
- Regex = a text pattern: pieces (
\d,[a-z],^ $) + quantifiers (+ * ? {n}) + groups. testfor yes/no,matchAllfor extraction,replacefor replacing; flagsg i u.- For email, HTML, URLs use dedicated tools.