Skip to content

JavaScript Regular Expressions

Mattscreative edited this page Feb 21, 2026 · 1 revision

JavaScript Regular Expressions Guide

Table of Contents


Introduction

Regular expressions (regex) are patterns used to match character combinations in strings. They're incredibly powerful for validation, searching, and text manipulation.


Creating Regular Expressions

// Using literal notation (recommended)
const pattern = /hello/;

// Using RegExp constructor
const pattern2 = new RegExp("hello");

// With flags
const caseInsensitive = /hello/i;
const global = /hello/g;
const multiline = /hello/m;

// Combined flags
const combined = /hello/gi;

Basic Patterns

// Literal characters - match exact string
/hello/.test("hello world");  // true
/hello/.test("Hello world");  // false (case-sensitive)

// Escape special characters with \
/\$10/.test("It costs $10");  // true
/\./test("end.");             // true

// Using special characters
/\d/.test("123");    // true - matches any digit
/\w/.test("abc_123"); // true - word character (letter, digit, underscore)
/\s/.test("a b");    // true - whitespace

Character Classes

// [] - match any character in brackets
/[aeiou]/.test("hello");    // true - matches any vowel
/[0-9]/.test("abc123");    // true - matches any digit
/[a-z]/.test("Hello");     // true - lowercase letter
/[A-Z]/.test("Hello");    // true - uppercase letter

// Negation with ^
/[^0-9]/.test("abc");    // true - not a digit
/[^aeiou]/.test("bcd");  // true - not a vowel

// Shorthand character classes
\d  // [0-9] - digit
\D  // [^0-9] - non-digit
\w  // [a-zA-Z0-9_] - word character
\W  // [^a-zA-Z0-9_] - non-word character
\s  // whitespace (space, tab, newline)
\S  // non-whitespace
.   // any character except newline

Quantifiers

// * - 0 or more
/ab*c/.test("ac");     // true
/ab*c/.test("abc");    // true
/ab*c/.test("abbbbc"); // true

// + - 1 or more
/ab+c/.test("abc");    // true
/ab+c/.test("ac");     // false

// ? - 0 or 1 (optional)
/colou?r/.test("color");   // true
/colou?r/.test("colour");  // true

// {n} - exactly n times
/\d{3}/.test("123");    // true
/\d{3}/.test("12");     // false

// {n,} - n or more times
/\d{2,}/.test("123");   // true
/\d{2,}/.test("1");     // false

// {n,m} - between n and m times
/\d{2,4}/.test("123");   // true
/\d{2,4}/.test("1");     // false

// Greedy vs Non-greedy
/<.*>/.test("<div>text</div>");     // true - greedy (matches most)
/<.*?>/.test("<div>text</div>");    // true - non-greedy

Anchors

// ^ - start of string
/^hello/.test("hello world");  // true
/^hello/.test("say hello");    // false

// $ - end of string
/world$/.test("hello world");  // true
/world$/.test("hello world!"); // false

// \b - word boundary
/\bword\b/.test("a word here");  // true
/\bword\b/.test("sword");         // false

// \B - non-word boundary
/\Bword/.test("sword");    // true
/\Bword/.test("a word");   // false

Groups and Capturing

// Parentheses create capturing groups
/(\d{3})-(\d{4})/.test("123-4567");  // true

// Capture groups - extract matches
const match = "123-4567".match(/(\d{3})-(\d{4})/);
console.log(match[0]);   // "123-4567" (full match)
console.log(match[1]);  // "123" (first group)
console.log(match[2]);  // "4567" (second group)

// Non-capturing groups (?:)
/(?:\d{3})-(\d{4})/.exec("123-4567");
// [ "123-4567", "4567" ] - only captures second group

// Named capture groups (?<name>)
const result = "2024-01-15".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
console.log(result.groups.year);   // "2024"
console.log(result.groups.month);  // "01"
console.log(result.groups.day);    // "15"

// Backreferences
/(\w+)\s\1/.test("hello hello");  // true - matches repeated word
/(\w+)\s\1/.test("hello world");  // false

Lookahead and Lookbehind

// Positive lookahead (?=)
// Match x followed by y (but don't include y)
/\d+(?=\s*dollars)/.exec("100 dollars")[0];  // "100"

// Negative lookahead (?!)
// Match x NOT followed by y
/\d+(?!\s*dollars)/.exec("100 euros")[0];    // "100"

// Positive lookbehind (?<=)
// Match x preceded by y
/(?<=\$)\d+/.exec("$100")[0];   // "100"

// Negative lookbehind (?<!)
/(?<!\$)\d+/.exec("100")[0];    // "100"

// Practical example - password validation
// At least 8 chars, one uppercase, one lowercase, one number
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
passwordRegex.test("Pass1234");  // true
passwordRegex.test("password");   // false

Flags

// g - global - find all matches
"hello hello hello".match(/hello/g);  // ["hello", "hello", "hello"]

// i - case insensitive
/Hello/i.test("hello");  // true

// m - multiline - ^ and $ match line starts/ends
const text = "first line\nsecond line";
/^second/.test(text);       // false
/^second/m.test(text);     // true

// s - dotall - . matches newlines
/./s.test("\n");    // true

// u - unicode - full unicode support
/^\u{1F600}$/u.test("😀");  // true - matches emoji

String Methods with Regex

const str = "Hello World, Hello Universe";

// match() - find matches
str.match(/Hello/);        // ["Hello"]
str.match(/Hello/gi);      // ["Hello", "Hello"]
str.match(/X/);           // null

// replace() - find and replace
str.replace(/Hello/, "Hi");     // "Hi World, Hello Universe"
str.replace(/Hello/gi, "Hi");   // "Hi World, Hi Universe"

// Using capture groups in replacement
str.replace(/(\w+), (\w+)/, "$2, $1");  // "World, Hello"

// replaceAll() - replace all matches (ES2021)
str.replaceAll("Hello", "Hi");  // "Hi World, Hi Universe"

// split() - split by regex
"a,b;c;d".split(/[,;]/);  // ["a", "b", "c", "d"]

// search() - find index of match
str.search(/World/);    // 6
str.search(/X/);        // -1 (not found)

// test() - boolean check
/hello/i.test("Hello World");  // true

// exec() - detailed match info
const regex = /\d+/g;
const result = regex.exec("abc 123 def 456");
console.log(result[0]);   // "123"
console.log(result.index); // 4

Regex Methods

const regex = /\d+/g;

// test() - returns true/false
regex.test("abc123def");  // true
regex.test("abcdef");     // false

// exec() - returns match info or null
const match = /(\d+)/.exec("abc 123 def");
if (match) {
    console.log(match[0]);     // "123"
    console.log(match[1]);     // "123" (first capture)
    console.log(match.index);  // 4
}

// lastIndex - for global regex
const globalRegex = /\d+/g;
globalRegex.lastIndex = 0;
console.log(globalRegex.exec("123")[0]);  // "123"
console.log(globalRegex.lastIndex);         // 3

Practical Examples

Email Validation

function validateEmail(email) {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(email);
}

console.log(validateEmail("test@example.com"));      // true
console.log(validateEmail("invalid"));             // false
console.log(validateEmail("@example.com"));         // false
console.log(validateEmail("test@.com"));            // false

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

Phone Number Validation

// US phone formats: (123) 456-7890, 123-456-7890, 123.456.7890
function validatePhone(phone) {
    const regex = /^\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$/;
    return regex.test(phone);
}

console.log(validatePhone("(123) 456-7890"));  // true
console.log(validatePhone("123-456-7890"));   // true
console.log(validatePhone("123.456.7890"));    // true
console.log(validatePhone("1234567890"));      // true
console.log(validatePhone("123-45-6789"));     // false

URL Validation

function validateURL(url) {
    const regex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
    return regex.test(url);
}

console.log(validateURL("https://example.com"));           // true
console.log(validateURL("http://www.example.com/page"));   // true
console.log(validateURL("ftp://example.com"));             // false
console.log(validateURL("example.com"));                   // false

Extract Information

// Extract dates from text
const text = "The event is on 2024-01-15 and 2024-02-20.";
const dates = text.match(/\d{4}-\d{2}-\d{2}/g);
console.log(dates);  // ["2024-01-15", "2024-02-20"]

// Extract numbers with units
const prices = "Price: $50, €75, £100";
const numbers = prices.match(/[$£]\d+/g);
console.log(numbers);  // ["$50", "€75", "£100"]

// Extract hashtags
const tweet = "Learning #JavaScript and #Programming!";
const hashtags = tweet.match(/#\w+/g);
console.log(hashtags);  // ["#JavaScript", "#Programming"]

Replace with Callbacks

// Convert currency symbols
const text = "Price: $50 and €75";
const converted = text.replace(/[$£]([\d.]+)/g, (match, number) => {
    return `$${number}`;
});
console.log(converted);  // "Price: $50 and $75"

// Highlight search terms
function highlight(text, term) {
    return text.replace(new RegExp(`(${term})`, 'gi'), '<mark>$1</mark>');
}

console.log(highlight("Hello World", "world"));
// "Hello <mark>World</mark>"

Form Validation

// Validate username
function validateUsername(username) {
    // 3-16 chars, alphanumeric and underscore only
    const regex = /^[a-zA-Z0-9_]{3,16}$/;
    return regex.test(username);
}

console.log(validateUsername("user123"));    // true
console.log(validateUsername("ab"));         // false (too short)
console.log(validateUsername("user-name"));  // false (hyphen not allowed)

// Validate password strength
function validatePassword(password) {
    const checks = [
        { regex: /.{8,}/, message: "At least 8 characters" },
        { regex: /[0-9]/, message: "At least one number" },
        { regex: /[a-z]/, message: "At least one lowercase" },
        { regex: /[A-Z]/, message: "At least one uppercase" },
        { regex: /[^a-zA-Z0-9]/, message: "At least one special character" }
    ];
    
    const errors = checks
        .filter(check => !check.regex.test(password))
        .map(check => check.message);
    
    return {
        valid: errors.length === 0,
        errors
    };
}

console.log(validatePassword("Pass1234"));
// { valid: true, errors: [] }

console.log(validatePassword("pass"));
// { valid: false, errors: [...] }

Common Regex Patterns

// Email
/^[^\s@]+@[^\s@]+\.[^\s@]+$/

// URL
/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/

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

// Date (YYYY-MM-DD)
/^\d{4}-\d{2}-\d{2}$/

// Date (MM/DD/YYYY)
/^\d{2}\/\d{2}\/\d{4}$/

// Time (24-hour)
/^([01]\d|2[0-3]):([0-5]\d)(:([0-5]\d))?$/

// IP Address (IPv4)
/^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/

// Hex Color Code
/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/

// Username (alphanumeric, 3-16 chars)
/^[a-zA-Z0-9_]{3,16}$/

// Strong password
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/

// HTML Tag
/<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)/i

// Credit Card Number
/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})$/

// Zip Code (US)
/^\d{5}(-\d{4})?$/

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

// UUID
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i

Quick Reference

// Character classes
\d   // digit [0-9]
\w   // word [a-zA-Z0-9_]
\s   // whitespace
.    // any char

// Quantifiers
*    // 0 or more
+    // 1 or more
?    // 0 or 1
{n}  // exactly n
{n,} // n or more
{n,m} // between n and m

// Anchors
^    // start
$    // end
\b   // word boundary

// Groups
()   // capturing group
(?:) // non-capturing

// Flags
g    // global
i    // case insensitive
m    // multiline

Clone this wiki locally