Development

Regex in JavaScript: From Beginner to Advanced Patterns

The Debuggers Engineering Team
13 min read

Code editor with regex pattern highlighting and match results

Regular expressions (regex) are one of the most powerful - and most feared - tools in a developer's arsenal. They can validate email addresses, parse log files, extract data from strings, and replace complex text patterns in a single line of code.

This guide takes you from zero to confident regex usage in JavaScript, covering basic syntax, quantifiers, groups, lookahead/lookbehind, and practical patterns you will use every day.

Regex Basics in JavaScript

In JavaScript, you create regex patterns in two ways:

// Literal syntax
const pattern = /hello/gi;

// Constructor syntax
const pattern = new RegExp('hello', 'gi');

Essential Flags

FlagMeaning
gGlobal - find all matches, not just the first
iCase-insensitive matching
mMultiline - ^ and $ match line boundaries
sDotall - . matches newlines
uUnicode - enable Unicode property escapes

Character Classes

Character classes match specific sets of characters:

\d    // Any digit [0-9]
\w    // Any word character [a-zA-Z0-9_]
\s    // Any whitespace (space, tab, newline)
\D    // NOT a digit
\W    // NOT a word character
.     // Any character (except newline by default)

Custom Character Classes

Use brackets to define custom sets:

[aeiou]    // Any vowel
[A-Z]      // Any uppercase letter
[0-9a-f]   // Any hex character
[^0-9]     // NOT a digit (negated class)

Quantifiers

Quantifiers control how many times a pattern repeats:

*      // 0 or more
+      // 1 or more
?      // 0 or 1
{3}    // Exactly 3
{2,5}  // Between 2 and 5
{3,}   // 3 or more

Greedy vs Lazy Matching

By default, quantifiers are greedy - they match as much as possible. Add ? to make them lazy:

const html = '<div>Hello</div><div>World</div>';

// Greedy: matches everything between first < and last >
html.match(/<.+>/);    // '<div>Hello</div><div>World</div>'

// Lazy: matches the smallest possible string
html.match(/<.+?>/);   // '<div>'

This is one of the most common sources of regex bugs. Always use lazy quantifiers when extracting content between delimiters.

Regex pattern matching demonstration showing greedy vs lazy quantifiers

Capturing Groups

Parentheses create capturing groups that extract specific parts of a match:

const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = '2026-03-02'.match(datePattern);

console.log(match[1]); // '2026' (year)
console.log(match[2]); // '03' (month)
console.log(match[3]); // '02' (day)

Named Capturing Groups

For readability, use named groups:

const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = '2026-03-02'.match(pattern);

console.log(match.groups.year);  // '2026'
console.log(match.groups.month); // '03'

Non-Capturing Groups

When you need grouping for logic but do not need the capture, use (?:...):

/(?:https?|ftp):\/\//  // Groups http/https/ftp but doesn't capture

Lookahead and Lookbehind

These are zero-width assertions - they check for a pattern without including it in the match.

Positive Lookahead (?=...)

Match something only if it is followed by a specific pattern:

// Match a number only if followed by "px"
const pattern = /\d+(?=px)/g;
'12px 8em 16px'.match(pattern);  // ['12', '16']

Negative Lookahead (?!...)

Match something only if it is NOT followed by a specific pattern:

// Match numbers NOT followed by "px"
const pattern = /\d+(?!px)/g;
'12px 8em 16px'.match(pattern);  // ['1', '8', '1']

Positive Lookbehind (?<=...)

Match something only if preceded by a specific pattern:

// Match amount after dollar sign
const pattern = /(?<=\$)\d+/g;
'$100 and €200'.match(pattern);  // ['100']

Negative Lookbehind (?<!...)

Match something only if NOT preceded by a specific pattern:

// Match numbers not preceded by $
const pattern = /(?<!\$)\d+/g;
'$100 and 200'.match(pattern);   // ['00', '200']

Practical Patterns You Will Use

Email Validation

const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

URL Extraction

const urlPattern = /https?:\/\/[^\s<>"{}|\\^`\[\]]+/g;

Password Strength

// At least 8 chars, 1 uppercase, 1 lowercase, 1 digit, 1 special
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;

Phone Number (International)

const phonePattern = /^\+?[1-9]\d{1,14}$/;

IP Address (v4)

const ipv4Pattern = /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/;

Common Mistakes to Avoid

  1. Catastrophic backtracking - Avoid nested quantifiers like (a+)+. They cause exponential time complexity on non-matching inputs.

  2. Forgetting to escape special characters - Characters like ., *, +, ?, (, ), [, ], {, }, \, ^, $, | have special meaning and must be escaped with \.

  3. Not anchoring validation patterns - Without ^ and $, your pattern does a partial match. "admin".match(/admin/) also matches "superadmin".

  4. Using regex for HTML parsing - Regex cannot handle nested structures. Use a DOM parser instead.

Testing Your Regex Patterns

Always test regex patterns against edge cases before deploying to production. Use our free Regex Tester to visualise matches, test against sample strings, and debug your patterns in real time - entirely in your browser.

Developer testing regex patterns in an online tester tool

Performance Tips

  1. Be specific - /[0-9]/ is faster than /\d/ in some engines because it avoids Unicode digit matching
  2. Avoid backtracking - Use atomic groups or possessive quantifiers when available
  3. Pre-compile patterns - If using the same regex in a loop, define it outside the loop
  4. Use test() for boolean checks - regex.test(string) is faster than string.match(regex) when you only need true/false

Frequently Asked Questions

What is the difference between test() and match() in JavaScript?

test() returns a boolean (true/false). match() returns the match result array or null. Use test() for validation, match() for extraction.

Can regex match across multiple lines?

Yes, use the m (multiline) flag to make ^ and $ match line boundaries, and the s (dotall) flag to make . match newlines.

How do I make regex case-insensitive?

Add the i flag: /pattern/i or new RegExp('pattern', 'i').

Need Help Implementing This in a Real Project?

Our team supports end-to-end development for web and mobile software, from architecture to launch.

regex tester onlineregular expression javascriptregex patternsregex lookaheadregex tutorial

Found this helpful?

Join thousands of developers using our tools to write better code, faster.