Validation, parsing logs and bulk text transformations all lean on regular expressions.
A regular expression describes a text pattern. Write a literal /pattern/flags, or new RegExp(string, flags) when the pattern is built at runtime.
Core syntax: \d digit, \w word character, \s whitespace, . any character (except newlines unless the s flag), [a-z] sets, ^/$ anchors, \b word boundary, quantifiers *, +, ?, {2,4} (add ? for lazy: +?), alternation a|b, groups ( ), non-capturing (?: ), named groups (?<year>\d{4}), and lookarounds (?=...), (?<!...).
Flags: g global, i case-insensitive, m multiline anchors, s dot matches newlines, u Unicode mode, v (ES2024) an upgraded Unicode mode with set operations, y sticky, d match indices.
The methods you'll use:
re.test(str)— boolean.str.match(re)— withoutg, a match with groups (m.groups.year); withg, an array of all matched strings.str.matchAll(re)— iterator of full match objects for agregex; the best way to extract many matches with groups.str.replace(re, replacement)/replaceAll— replacement strings can reference$1or$<name>, or pass a function.str.split(re).
The classic trap: a regex with g or y is stateful — test and exec advance re.lastIndex, so reusing the same regex can alternate between true and false. Don't share global regexes for test.
When putting user input into a pattern, escape it. ES2025 adds RegExp.escape(str) for exactly that. And keep patterns modest: nested quantifiers like (a+)+ can backtrack catastrophically on some inputs (ReDoS). For HTML, URLs and dates, prefer real parsers such as URL and Intl.
Example
const log = "2025-03-14 ERROR db timeout\n2025-03-15 INFO ok\n2025-03-16 ERROR disk full";
const re = /^(?<date>\d{4}-\d{2}-\d{2}) ERROR (?<msg>.+)$/gm;
for (const m of log.matchAll(re)) {
console.log(m.groups.date, "->", m.groups.msg);
}
// 2025-03-14 -> db timeout
// 2025-03-16 -> disk full
const iso = "2025-03-14";
console.log(iso.replace(/(?<y>\d+)-(?<m>\d+)-(?<d>\d+)/, "$<d>/$<m>/$<y>")); // 14/03/2025
console.log("snake_case_name".replace(/_(\w)/g, (_, c) => c.toUpperCase())); // snakeCaseName
const g = /a/g;
console.log(g.test("a"), g.test("a")); // true false (lastIndex moved!)
console.log(/^\p{Lu}/u.test("Élan")); // true: Unicode property escapeRemember
- Use named groups and
matchAllto extract structured data - Regexes with
g/ykeeplastIndexstate — don't reuse them fortest - Escape user input (
RegExp.escapein ES2025) and avoid nested quantifiers
Watch out for
- Building a RegExp from user input without escaping special characters.