Regular Expressions
A regular expression (regex) is a tiny pattern language for describing shapes of text. Instead of writing loops that step through a string character by character, you tell the engine what you are looking for — "three digits", "a word that ends in -ing", "an email-shaped thing" — and it scans for you. JavaScript ships with a fully featured regex engine and a built-in RegExp type, so you can use patterns directly in your code.
Two ways to create a regex
There are two equivalent forms. Pick whichever reads better at the call site.
Literal form
// Slashes wrap the pattern. Flags go after the closing slash.
const re1 = /hello/i;
console.log(re1.test("Hello, world!")); // true (case-insensitive)Constructor form
// Useful when the pattern is built from a string at runtime.
const word = "hello";
const re2 = new RegExp(word, "i");
console.log(re2.test("HELLO there")); // trueAnatomy of a pattern
A regex is just text, but most characters mean themselves and a handful have special powers. The literal /cat/ matches the three letters c, a, t in that order. Special characters add shape:
.— any single character except a newline.\d— a digit (0–9).\Dis the opposite.\w— a "word" character (letters, digits, underscore).\Wis the opposite.\s— whitespace (space, tab, newline).\Sis the opposite.^and$— anchors meaning start and end of input (or of a line with themflag).[abc]— a character class. Match any one ofa,b, orc.a|b— alternation. Matchaorb.a*a+a?a{2,4}— quantifiers: zero or more, one or more, optional, between 2 and 4 times.
We cover these in detail on the next page. For now, just know that a regex describes a shape, and JavaScript gives you methods to ask "does this string match the shape?" or "find all matches".
The two everyday methods: test and exec
RegExp.prototype.test(str) returns a boolean — perfect for validation. RegExp.prototype.exec(str) returns the first match (with details) or null.
Yes-or-no with test
const isHexColour = /^#[0-9a-f]{6}$/i;
console.log(isHexColour.test("#FF00aa")); // true
console.log(isHexColour.test("red")); // false
console.log(isHexColour.test("#1234")); // falsetrue false false
Details with exec
const re = /(\d{4})-(\d{2})-(\d{2})/;
const result = re.exec("Today is 2026-05-13, tomorrow is 2026-05-14");
console.log(result[0]); // "2026-05-13" — the full match
console.log(result[1]); // "2026" — first capturing group
console.log(result[2]); // "05"
console.log(result[3]); // "13"
console.log(result.index);// 9 — where the match started2026-05-13 2026 05 13 9
String methods that take a regex
Strings have their own methods that accept a regex — often nicer than calling exec in a loop.
const text = "apples 3, oranges 12, pears 7"; text.match(/\d+/); // ["3", index: 7, ...] text.match(/\d+/g); // ["3", "12", "7"] text.replace(/\d+/g, "#"); // "apples #, oranges #, pears #" text.split(/,\s*/); // ["apples 3", "oranges 12", "pears 7"] text.search(/oranges/); // 10 — index, or -1
Three common cases
Most real-world regex code falls into a few buckets. Here are three you will write again and again.
1. Validation
const isFiveDigitZip = /^\d{5}$/;
isFiveDigitZip.test("90210"); // true
isFiveDigitZip.test("9021"); // false
isFiveDigitZip.test("90210x"); // false (anchors keep junk out)2. Extraction
const log = "GET /users 200 12ms";
const m = log.match(/^(\w+) (\S+) (\d+) (\d+)ms$/);
if (m) {
const [, method, path, status, ms] = m;
console.log({ method, path, status: Number(status), ms: Number(ms) });
}{ method: 'GET', path: '/users', status: 200, ms: 12 }3. Search and replace
const messy = " hello, world "; messy .trim() .replace(/\s+/g, " ") .replace(/,(\S)/g, ", $1"); // "hello, world"
Flags at a glance
Flags go after the closing slash (or as the second argument to new RegExp). The most common ones:
g— global. Find all matches, not just the first.i— case-insensitive.m— multi-line.^and$match at line breaks too.s— dotAll..also matches newlines.u— Unicode. Treat the pattern as Unicode (needed for\p{...}).y— sticky. Match only atlastIndex, no scanning forward.