All topics
Frontend · Learning hub

Regex notes for developers

Master Regex with a curated set of 3 developer notes — core concepts, patterns, and interview prep. Maintained by the DevRecall team.

Save this stack to your DevRecallMore Frontend notes
Regex

Regular Expressions

Regular Expressions Syntax Reference # Character classes . any character except newline \d digit [0-9] \D non-digit \w word char [a-zA-Z0-9_] \W non-word char \

Regular Expressions

Syntax Reference

# Character classes
.        any character except newline
\d       digit [0-9]
\D       non-digit
\w       word char [a-zA-Z0-9_]
\W       non-word char
\s       whitespace (space, tab, newline)
\S       non-whitespace
[abc]    any of a, b, c
[^abc]   none of a, b, c
[a-z]    range a to z
[a-zA-Z0-9] alphanumeric

# Anchors
^        start of string (or line with m flag)
$        end of string (or line with m flag)
\b       word boundary  \bcat\b matches "cat" not "catch"
\B       non-word boundary

# Quantifiers
*        0 or more (greedy)
+        1 or more (greedy)
?        0 or 1
{n}      exactly n
{n,}     n or more
{n,m}    between n and m
*?  +?  ?? {n,m}?   non-greedy (lazy) versions

# Groups & alternation
(abc)    capturing group
(?:abc)  non-capturing group
(?<name>abc)  named capture group
a|b      a or b
\1       backreference to group 1

# Lookahead / Lookbehind
(?=abc)  positive lookahead  — followed by abc
(?!abc)  negative lookahead  — not followed by abc
(?<=abc) positive lookbehind — preceded by abc
(?<!abc) negative lookbehind — not preceded by abc

# Flags (JavaScript)
g  global (find all matches)
i  case-insensitive
m  multiline (^ $ match line start/end)
s  dotAll (. matches newline)
u  unicode
d  indices (match.indices)

JavaScript Regex API

// Test — boolean
/^\d{4}$/.test('2024')            // true
/^\d{4}$/.test('abc')             // false

// Match — first match (or all with /g)
'hello world'.match(/\w+/)        // ['hello', index: 0, ...]
'hello world'.match(/\w+/g)       // ['hello', 'world']

// MatchAll — iterator of all matches with groups
const re = /(?<year>\d{4})-(?<month>\d{2})/g;
for (const m of '2024-01 and 2025-06'.matchAll(re)) {
  console.log(m.groups.year, m.groups.month);
}

// Replace
'foo bar'.replace(/\s+/, '-')     // 'foo-bar' (first only)
'foo bar baz'.replace(/\s+/g, '-')// 'foo-bar-baz' (all)
// With function
'hello'.replace(/(\w+)/, (_, w) => w.toUpperCase()) // 'HELLO'

// Split
'one, two,  three'.split(/,\s*/)  // ['one', 'two', 'three']

// Named capture groups
const m = '2024-03-07'.match(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/);
const { y, m: month, d } = m.groups;  // '2024', '03', '07'

Common Patterns

// Email (simplified)
/^[^\s@]+@[^\s@]+\.[^\s@]+$/

// URL
/^https?:\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?$/

// IPv4
/^(\d{1,3}\.){3}\d{1,3}$/

// Phone (US)
/^\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/

// Date YYYY-MM-DD
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/

// Hex color
/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/

// Slug (URL-friendly)
/^[a-z0-9]+(?:-[a-z0-9]+)*$/

// Credit card (basic)
/^\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}$/

// Password (min 8, uppercase, lowercase, digit, special)
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z\d]).{8,}$/

// Strip HTML tags
str.replace(/<[^>]*>/g, '')

// Trim multiple spaces
str.replace(/\s+/g, ' ').trim()

// CamelCase to snake_case
str.replace(/([A-Z])/g, '_$1').toLowerCase()

// Extract all numbers
str.match(/-?\d+(\.\d+)?/g)
Regex

Regex Fundamentals

Regex Fundamentals Regular expressions are patterns for matching character combinations in strings. In JavaScript, regex literals are written as /pattern/flags

Regex Fundamentals

Regular expressions are patterns for matching character combinations in strings. In JavaScript, regex literals are written as /pattern/flags or constructed via new RegExp(pattern, flags).

Character Classes & Anchors

# Character classes
.        any character except newline
\d       digit [0-9]
\D       non-digit
\w       word char [a-zA-Z0-9_]
\W       non-word char
\s       whitespace (space, tab, newline)
\S       non-whitespace
[abc]    any of a, b, c
[^abc]   none of a, b, c
[a-z]    range a to z
[a-zA-Z0-9] alphanumeric

# Anchors
^        start of string (or line with m flag)
$        end of string (or line with m flag)
\b       word boundary  — \bcat\b matches "cat" not "catch"
\B       non-word boundary

# Quantifiers
*        0 or more (greedy)
+        1 or more (greedy)
?        0 or 1
{n}      exactly n
{n,}     n or more
{n,m}    between n and m
*?  +?  ??  {n,m}?   non-greedy (lazy) versions

Groups & Lookahead / Lookbehind

# Groups
(abc)          capturing group
(?:abc)        non-capturing group (no capture overhead)
(?<name>abc)   named capture group
a|b            alternation: a or b
\1             backreference to group 1

# Lookahead & lookbehind (zero-width assertions)
(?=abc)   positive lookahead  — position must be followed by abc
(?!abc)   negative lookahead  — position must NOT be followed by abc
(?<=abc)  positive lookbehind — position must be preceded by abc
(?<!abc)  negative lookbehind — position must NOT be preceded by abc

# Examples
\d+(?= dollars)   matches a number only if followed by " dollars"
(?<!\d)\d{4}      matches 4-digit number NOT preceded by a digit

JavaScript Regex API

// test() — returns boolean
/^\d{4}$/.test('2024')            // true
/^\d{4}$/.test('abc')             // false

// match() — first match (or all matches with /g flag)
'hello world'.match(/\w+/)        // ['hello', index: 0, input: ...]
'hello world'.match(/\w+/g)       // ['hello', 'world']

// matchAll() — iterator over all matches (requires /g flag)
const re = /(?<year>\d{4})-(?<month>\d{2})/g;
for (const m of '2024-01 and 2025-06'.matchAll(re)) {
  console.log(m.groups.year, m.groups.month);
}

// replace() / replaceAll()
'foo bar'.replace(/\s+/, '-')          // 'foo-bar' (first only)
'foo bar baz'.replace(/\s+/g, '-')     // 'foo-bar-baz'
// Replace with function (match, group1, offset, string)
'hello world'.replace(/(\w+)/g, (match) => match.toUpperCase())  // 'HELLO WORLD'

// split()
'one, two,  three'.split(/,\s*/)   // ['one', 'two', 'three']

// exec() — stateful; advances lastIndex with /g
const pattern = /\d+/g;
let result;
while ((result = pattern.exec('1 fish 2 fish')) !== null) {
  console.log(result[0], 'at index', result.index);
}

Named Capture Groups

// Named groups — access via match.groups
const dateRe = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const m = '2024-03-15'.match(dateRe);
const { year, month, day } = m.groups;  // '2024', '03', '15'

// Named groups in replace()
'John Smith'.replace(
  /(?<first>\w+) (?<last>\w+)/,
  '$<last>, $<first>'   // 'Smith, John'
);

// Named groups in replaceAll with function
'2024-01-15 and 2025-06-20'.replaceAll(
  /(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/g,
  (_, y, mo, d) => `${mo}/${d}/${y}`
);
// '01/15/2024 and 06/20/2025'
Regex

Common Patterns

Common Regex Patterns A collection of battle-tested patterns for validating and extracting common data formats in JavaScript and TypeScript. Validation Patterns

Common Regex Patterns

A collection of battle-tested patterns for validating and extracting common data formats in JavaScript and TypeScript.

Validation Patterns

// Email (simplified but practical)
const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
emailRe.test('user@example.com')   // true
emailRe.test('bad@')               // false

// URL (http/https)
const urlRe = /^https?:\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?$/;

// IPv4 address
const ipv4Re = /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;

// Phone number (US, flexible format)
const phoneRe = /^\+?1?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$/;
phoneRe.test('(555) 123-4567')    // true
phoneRe.test('+1 555.123.4567')   // true

// Date YYYY-MM-DD
const dateRe = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;

// Hex color  #rgb or #rrggbb
const hexColorRe = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;

// URL-friendly slug
const slugRe = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;

// Password: min 8, uppercase, lowercase, digit, special char
const strongPasswordRe = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z\d]).{8,}$/;

// Credit card (basic 16-digit check)
const ccRe = /^\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}$/;

Regex Flags

// g — global: find all matches (not just first)
'aaa'.match(/a/g)              // ['a', 'a', 'a']

// i — case-insensitive
/hello/i.test('Hello World')   // true

// m — multiline: ^ and $ match line start/end
const lines = 'first\nsecond\nthird';
lines.match(/^\w+/gm)          // ['first', 'second', 'third']

// s — dotAll: . matches newline too
/hello.world/s.test('hello\nworld')  // true (without s: false)

// u — unicode: enables full Unicode support
/\u{1F600}/u.test('\u{1F600}')  // true (emoji match)

// d — hasIndices: match.indices contains start/end positions
const result = /foo/d.exec('foobar');
console.log(result.indices[0]);  // [0, 3]

// Combining flags
/pattern/gim    // global + case-insensitive + multiline
new RegExp('pattern', 'gim')  // equivalent constructor form

Real-World Usage in JS/TS

// Strip HTML tags
const stripped = html.replace(/<[^>]*>/g, '');

// Trim multiple whitespace to single space
const normalized = str.replace(/\s+/g, ' ').trim();

// CamelCase to kebab-case
const kebab = str
  .replace(/([A-Z])/g, '-$1')
  .toLowerCase()
  .replace(/^-/, '');
// 'myVariableName' -> 'my-variable-name'

// Extract all numbers (including decimals and negatives)
const numbers = str.match(/-?\d+(\.\d+)?/g)?.map(Number) ?? [];

// Escape special regex characters for dynamic patterns
function escapeRegex(str: string): string {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const safe = escapeRegex('1 + 2 = 3');
new RegExp(safe).test('1 + 2 = 3');  // true

// Zod-style validation helper with regex
function validate(value: string, pattern: RegExp, message: string) {
  if (!pattern.test(value)) throw new Error(message);
  return value;
}
validate(email, /^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'Invalid email');

// Template variable replacement
const template = 'Hello, {{name}}! You have {{count}} messages.';
const data = { name: 'Alice', count: '5' };
const output = template.replace(/\{\{(\w+)\}\}/g, (_, key) => data[key] ?? '');
// 'Hello, Alice! You have 5 messages.'

Keep your Regex knowledge sharp.

Save this stack to your personal DevRecall — add your own notes, track what you're learning, and share what you know with the community.

Get started — free forever