RegExp
The built-in for pattern matching in strings. Define a pattern, then test, match, or replace text with it.
When to use it
- Validation — check if a string matches a format (email, phone, URL)
- Extraction — pull structured data out of text (dates, IDs, tokens)
- Search and replace — transform strings with patterns
- Splitting — break a string apart on a complex delimiter
Anatomy
const re = /pattern/flags // literal syntax
const re2 = new RegExp('pattern', 'flags') // constructor (dynamic patterns)
// flags
/g/ // global — find all matches, not just the first
/i/ // case-insensitive
/m/ // multiline — ^ and $ match line boundaries
/s/ // dotAll — . matches newlines too
/u/ // unicode — correct handling of surrogate pairs
// methods
re.test('string') // true/false — does it match?
'string'.match(re) // array of matches or null
'string'.matchAll(re) // iterator of all matches with groups (needs /g)
'string'.replace(re, 'new') // replace matches
'string'.search(re) // index of first match or -1
'string'.split(re) // split on patternAt a glance
| Method | What it does |
|---|---|
re.test(str) | Boolean — does the string match? |
str.match(re) | First match (or all with /g) |
str.matchAll(re) | Iterator of all matches with capture groups |
str.replace(re, new) | Replace matches |
str.replaceAll(re, new) | Replace all (requires /g flag) |
str.search(re) | Index of first match |
str.split(re) | Split string on pattern |
Common patterns
| Pattern | What it matches |
|---|---|
. | Any character (except newline) |
\d | Digit (0-9) |
\w | Word character (letter, digit, underscore) |
\s | Whitespace (space, tab, newline) |
^ / $ | Start / end of string |
* / + / ? | 0+, 1+, 0 or 1 repetitions |
{n} / {n,m} | Exactly n / between n and m repetitions |
[abc] | Character class — a, b, or c |
[^abc] | Negated class — not a, b, or c |
(group) | Capture group |
(?:group) | Non-capturing group |
(?<name>group) | Named capture group |
1. Simple — test a pattern
const emailish = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
// ^ — start of string
// [^\s@]+ — one or more chars that aren't whitespace or @
// @ — literal @
// [^\s@]+ — domain name
// \. — literal dot
// [^\s@]+$ — TLD through end of string
emailish.test('alice@test.com') // true
emailish.test('not an email') // false2. Intermediate — named capture groups
const datePattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const match = '2026-03-15'.match(datePattern)
match.groups.year // '2026'
match.groups.month // '03'
match.groups.day // '15'3. Advanced — replace with a function
// convert markdown bold to HTML
const md = 'This is **bold** and **important**'
const html = md.replace(/\*\*(.+?)\*\*/g, (fullMatch, content) => {
// fullMatch = '**bold**'
// content = 'bold' (first capture group)
return `<strong>${content}</strong>`
})
// 'This is <strong>bold</strong> and <strong>important</strong>'Gotchas
Forgetting the global flag
'aaa'.match(/a/) // ['a'] — only the first match
'aaa'.match(/a/g) // ['a', 'a', 'a'] — all matches
// matchAll always requires /g
'aaa'.matchAll(/a/) // TypeError: must be called with a global RegExpStateful global regexes
const re = /a/g
re.test('abc') // true — lastIndex moves to 1
re.test('abc') // false — starts searching from index 1, finds nothing
re.test('abc') // true — lastIndex reset to 0 after a failed match
// each .test() or .exec() on a /g regex advances lastIndex
// create a new regex or use string methods to avoid thisRelated
Last updated on