Mastering Regular Expressions in JavaScript

Regular expressions are patterns used to match character combinations in strings. In JavaScript, they are implemented as RegExp objects and integrate with both RegExp instance methods (exec, test) and String prototype methods (match, matchAll, replace, search, split).

Constructing Regular Expressions

Two primary approaches exist:

Literal notation: Defined using forward slashes.

const pattern = /hello\d+/;

This form compiles at parse time—ideal for static patterns and better performance.

Constructor syntax: Built dynamically via RegExp.

const digits = '123';
const pattern = new RegExp(`hello${digits}`, 'i');

Use this when the pattern is derived from runtime data (e.g., user input), since it supports interpolated strings and flags.

Pattern Composition

Patterns combine literal characters (e.g., /cat/) and metacharacters that convey logic (e.g., /c[aeiou]t/, /\d{3}-\d{2}-\d{4}/). Parentheses () create capturing groups, enabling extraction and reuse of matched substrings.

Literal Matching

A pattern like /dog/ matches only the exact sequence 'dog'. It succeeds in 'My dog barks' but fails in 'dogma' if anchored or in 'D.O.G.' without case-insensitive or dot-handling flags.

Metacharacters and Quantifiers

To express variability, use quantifiers and assertions:

  • *: zero or more of the preceding element (/ab*/ matches 'a', 'ab', 'abb').
  • +: one or more (/\w+/ matches 'hello' in 'hello world').
  • ?: zero or one; also toggles lazy matching when appended to another quantifier (/a+?/ matches 'a' in 'aaab', not 'aaa').
  • {n,m}: between n and m occurrences (/\d{2,4}/ matches '12', '123', '1234').
  • ^ and $: assert start and end of input (or line with m flag).
  • \b: word boundary (/\bcat\b/ matches 'cat' but not 'scatter').
  • |: alternation (/red|blue/ matches either substring).

Character Classes

  • \d: digit ([0-9]).
  • \w: word character ([A-Za-z0-9_]).
  • \s: whitespace ([ \f\n\r\t\v\u0020\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]).
  • [abc]: matches any of a, b, or c.
  • [^xyz]: matches any character except x, y, or z.

Assertions

  • (?=...): positive lookahead — matches only if followed by the pattern.
  • (?!...): negative lookahead — matches only if not followed by the pattern.
  • (?<=...): positive lookbehind — matches only if preceded by the pattern.
  • (?<!...): negative lookbehind — matches only if not preceded by the pattern.

Groups

  • (x): capturing group — stores matched content for backreference ($1, $2) or programmatic access (result[1]).
  • (?:x): non-capturing group — applies grouping logic without memory overhead.

Escaping Special Characters

To treat a metacharacter literally (e.g., match . instead of "any character"), prefix it with \\:

const literalDot = /\./; // matches '.'
const pathPattern = /C:\\Users\\[^\\]+/; // matches Windows paths

When building from strings, double-escape backslashes:

const patternStr = 'C:\\Users\\';
const re = new RegExp(patternStr + '[^\\]+');

For safe dynamic escaping of arbitrary strings:

function escapeForRegex(str) {
  return str.replace(/[\[\]{}()*+?.^$|\\]/g, '\\$&');
}

Core Methods

Method Context Return Notes
exec() RegExp Array or null Returns full match + captures; updates lastIndex with g flag.
test() RegExp boolean Fast boolean check; no capture data.
match() String Array or null Like exec(), but called on string. With g, returns matches only (no groups).
matchAll() String Iterator Yields all matches with full detail (including groups).
replace() String string Substitutes matches; supports $1, $2, functions.
search() String number Returns first match index or -1.
split() String Array Splits on matches; empty strings retained if adjacent delimiters.

Example using exec with global state:

const re = /\b(\w+)\b/g;
const text = 'Hello world! Hello again!';
let match;

while ((match = re.exec(text)) !== null) {
  console.log(`Found '${match[0]}' at position ${match.index}`);
  // Captured group: match[1]
}

Flags

Flags modify matching behavior and are appended after the closing slash (literal) or passed as second argument (constructor):

  • g: global — finds all matches, not just the first.
  • i: case-insensitive.
  • m: multiline — ^/$ match line boundaries.
  • s: dotAll — . matches newlines.
  • u: Unicode — enables full Unicode support (e.g., \u{1F600} emojis).
  • y: sticky — matches only from lastIndex; useful for incremental parsing.

Example with multiple flags:

const re = /\bhello\b/giu;
// or
const re2 = new RegExp('\\bhello\\b', 'giu');

Practical Examples

Reordering name components:

const fullName = 'Jane Doe';
const swapped = fullName.replace(/^(\w+)\s+(\w+)$/, '$2, $1');
// → 'Doe, Jane'

Validating US phone numbers (flexible formatting):

const phoneRE = /^(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}$/;
console.log(phoneRE.test('(123) 456-7890')); // false — space breaks pattern
console.log(phoneRE.test('(123)456-7890'));   // true

Splititng and transforming delimited data:

const raw = 'Alice ;  Bob  ;  Charlie';
const names = raw.split(/\s*;\s*/).map(n => n.trim());
const formatted = names.map(name => name.replace(/^(\w+)\s+(\w+)$/, '$2, $1'));
// → ['Bob, Alice', 'Charlie'] (if two-part names only)

Tags: javascript regex pattern-matching string-processing

Posted on Sat, 07 Nov 2026 16:03:32 +0000 by phparray