Regular expressions

JavaScript · Advanced · 15 min

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) — without g, a match with groups (m.groups.year); with g, an array of all matched strings.
  • str.matchAll(re) — iterator of full match objects for a g regex; the best way to extract many matches with groups.
  • str.replace(re, replacement) / replaceAll — replacement strings can reference $1 or $<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 escape

Remember

  • Use named groups and matchAll to extract structured data
  • Regexes with g/y keep lastIndex state — don't reuse them for test
  • Escape user input (RegExp.escape in ES2025) and avoid nested quantifiers

Watch out for

  • Building a RegExp from user input without escaping special characters.

Check yourself

  1. const re = /x/g; console.log(re.test("x"), re.test("x")); — what is printed?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions

Builds on

Unlocks

Nothing builds on this yet.