Regular Expressions: The 10 Patterns You Actually Use

TL;DR

Learn 10 regex patterns: email, URL, phone, credit card, password strength, whitespace, special chars, numbers, dates, and file extensions. Test on regex101.com. Use named groups. Avoid catastrophic backtracking.

I avoided regex for years. The syntax looked like random characters. Then I spent 3 hours parsing emails with string methods and realized regex does it in one line.

Now I use regex daily. But I only use about 10 patterns repeatedly. Here they are.

Why Regex?

// Without regex - messy
function validateEmail(email) {
    if (!email.includes('@')) return false;
    const parts = email.split('@');
    if (parts.length !== 2) return false;
    if (parts[0].length === 0) return false;
    if (parts[1].length === 0) return false;
    if (!parts[1].includes('.')) return false;
    // ... 20 more checks
    return true;
}

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

Regex is for pattern matching. If you're checking format, use regex.

Pattern 1: Email Validation

// Simple (good enough for 95% of cases)
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

emailRegex.test('user@example.com');      // true
emailRegex.test('user.name@example.com'); // true
emailRegex.test('user+tag@example.com');  // true
emailRegex.test('invalid');               // false
emailRegex.test('invalid@');              // false
emailRegex.test('@example.com');          // false

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

// With named groups (ES2018+)
const emailWithGroups = /^(?<local>[^\s@]+)@(?<domain>[^\s@]+)$/;
const match = 'user@example.com'.match(emailWithGroups);
console.log(match.groups.local);  // "user"
console.log(match.groups.domain); // "example.com"

Breakdown:

^          Start of string
[^\s@]+    One or more characters that aren't space or @
@          Literal @ symbol
[^\s@]+    One or more characters that aren't space or @
\.         Literal dot (escaped)
[^\s@]+    One or more characters that aren't space or @
$          End of string

Pattern 2: URL Validation and Extraction

// Validate URL
const urlRegex = /^https?:\/\/[^\s]+$/;

urlRegex.test('https://example.com');        // true
urlRegex.test('http://example.com/path');    // true
urlRegex.test('not a url');                  // false

// Extract URLs from text
const urlExtractRegex = /https?:\/\/[^\s]+/g;

const text = 'Check out https://example.com and http://test.com';
const urls = text.match(urlExtractRegex);
console.log(urls);
// ["https://example.com", "http://test.com"]

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

// Extract domain from URL
const domainRegex = /^https?:\/\/([^\/]+)/;
const domain = 'https://example.com/path'.match(domainRegex)[1];
console.log(domain); // "example.com"

Pattern 3: Phone Numbers

// US phone number (flexible)
const phoneRegex = /^\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$/;

phoneRegex.test('555-123-4567');   // true
phoneRegex.test('(555) 123-4567'); // true
phoneRegex.test('5551234567');     // true
phoneRegex.test('555.123.4567');   // true

// Extract phone number parts
const match = '(555) 123-4567'.match(phoneRegex);
console.log(match[1]); // "555"
console.log(match[2]); // "123"
console.log(match[3]); // "4567"

// Format phone number
function formatPhone(phone) {
    const match = phone.replace(/\D/g, '').match(/^(\d{3})(\d{3})(\d{4})$/);
    return match ? `(${match[1]}) ${match[2]}-${match[3]}` : phone;
}

formatPhone('5551234567'); // "(555) 123-4567"

Pattern 4: Credit Card Numbers

// Visa, Mastercard, Amex, Discover
const visaRegex = /^4[0-9]{12}(?:[0-9]{3})?$/;
const mastercardRegex = /^5[1-5][0-9]{14}$/;
const amexRegex = /^3[47][0-9]{13}$/;
const discoverRegex = /^6(?:011|5[0-9]{2})[0-9]{12}$/;

// Remove spaces and dashes
function validateCard(card) {
    const cleaned = card.replace(/[\s-]/g, '');

    if (visaRegex.test(cleaned)) return 'Visa';
    if (mastercardRegex.test(cleaned)) return 'Mastercard';
    if (amexRegex.test(cleaned)) return 'Amex';
    if (discoverRegex.test(cleaned)) return 'Discover';

    return 'Invalid';
}

validateCard('4532 1234 5678 9010'); // "Visa"
validateCard('5425-2334-3010-9903'); // "Mastercard"

// Mask credit card
function maskCard(card) {
    return card.replace(/\d(?=\d{4})/g, '*');
}

maskCard('4532123456789010'); // "************9010"

Pattern 5: Password Strength

// At least 8 characters, 1 uppercase, 1 lowercase, 1 number
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;

passwordRegex.test('Password1');   // true
passwordRegex.test('password1');   // false (no uppercase)
passwordRegex.test('PASSWORD1');   // false (no lowercase)
passwordRegex.test('Password');    // false (no number)
passwordRegex.test('Pass1');       // false (too short)

// With special character requirement
const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/;

strongPasswordRegex.test('Password1!'); // true
strongPasswordRegex.test('Password1');  // false (no special char)

// Check password strength
function checkPasswordStrength(password) {
    const checks = {
        length: password.length >= 8,
        uppercase: /[A-Z]/.test(password),
        lowercase: /[a-z]/.test(password),
        number: /\d/.test(password),
        special: /[@$!%*?&#]/.test(password)
    };

    const score = Object.values(checks).filter(Boolean).length;

    if (score === 5) return 'Strong';
    if (score >= 3) return 'Medium';
    return 'Weak';
}

console.log(checkPasswordStrength('Password1!')); // "Strong"
console.log(checkPasswordStrength('password'));   // "Weak"

Breakdown of lookaheads:

(?=.*[a-z])    Look ahead for lowercase letter
(?=.*[A-Z])    Look ahead for uppercase letter
(?=.*\d)       Look ahead for digit
.{8,}          At least 8 characters

Pattern 6: Whitespace Handling

// Remove extra whitespace
const text = '  Hello    world  ';
text.replace(/\s+/g, ' ').trim(); // "Hello world"

// Remove all whitespace
text.replace(/\s/g, ''); // "Helloworld"

// Replace newlines with spaces
const multiline = 'Line 1\nLine 2\r\nLine 3';
multiline.replace(/\r?\n/g, ' '); // "Line 1 Line 2 Line 3"

// Trim each line
const lines = text.split('\n').map(line => line.trim());

// Remove empty lines
text.replace(/^\s*[\r\n]/gm, '');

Pattern 7: Extract Numbers

// Extract all numbers
const text = 'I have 5 apples and 10 oranges';
const numbers = text.match(/\d+/g);
console.log(numbers); // ["5", "10"]

// Extract decimal numbers
const prices = 'Items cost $19.99 and $5.50';
const amounts = prices.match(/\d+\.\d+/g);
console.log(amounts); // ["19.99", "5.50"]

// Extract negative numbers
const data = 'Temp is -5 degrees';
const temp = data.match(/-?\d+/);
console.log(temp[0]); // "-5"

// Parse formatted numbers
const formatted = '1,234,567.89';
const number = parseFloat(formatted.replace(/,/g, ''));
console.log(number); // 1234567.89

Pattern 8: Special Character Removal

// Remove special characters, keep alphanumeric
const text = 'Hello! How are you? #coding';
text.replace(/[^a-zA-Z0-9\s]/g, ''); // "Hello How are you coding"

// Keep only alphanumeric and dash/underscore
text.replace(/[^a-zA-Z0-9-_]/g, '');

// Slugify (URL-friendly)
function slugify(text) {
    return text
        .toLowerCase()
        .trim()
        .replace(/[^\w\s-]/g, '')   // Remove special chars
        .replace(/[\s_-]+/g, '-')   // Replace spaces with dash
        .replace(/^-+|-+$/g, '');   // Trim dashes
}

slugify('Hello World! This is a Test'); // "hello-world-this-is-a-test"

Pattern 9: Date Formats

// Match date formats
const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
const usDateRegex = /^\d{2}\/\d{2}\/\d{4}$/;
const euDateRegex = /^\d{2}\.\d{2}\.\d{4}$/;

isoDateRegex.test('2026-02-10'); // true
usDateRegex.test('02/10/2026');  // true
euDateRegex.test('10.02.2026');  // true

// Extract date parts
const dateRegex = /^(\d{4})-(\d{2})-(\d{2})$/;
const match = '2026-02-10'.match(dateRegex);
console.log(match[1]); // "2026" (year)
console.log(match[2]); // "02" (month)
console.log(match[3]); // "10" (day)

// Convert date formats
function convertDate(date) {
    const match = date.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
    if (match) {
        return `${match[3]}-${match[1]}-${match[2]}`; // MM/DD/YYYY → YYYY-MM-DD
    }
    return date;
}

convertDate('02/10/2026'); // "2026-02-10"

Pattern 10: File Extensions

// Check file extension
const imageRegex = /\.(jpg|jpeg|png|gif|webp)$/i;
const videoRegex = /\.(mp4|avi|mov|wmv)$/i;
const documentRegex = /\.(pdf|doc|docx|txt)$/i;

imageRegex.test('photo.jpg');      // true
imageRegex.test('photo.JPG');      // true (case-insensitive)
imageRegex.test('document.pdf');   // false

// Extract filename and extension
const fileRegex = /^(.+)\.([^.]+)$/;
const match = 'document.pdf'.match(fileRegex);
console.log(match[1]); // "document"
console.log(match[2]); // "pdf"

// Replace extension
function changeExtension(filename, newExt) {
    return filename.replace(/\.[^.]+$/, `.${newExt}`);
}

changeExtension('photo.jpg', 'png'); // "photo.png"

Common Regex Flags

// i = case-insensitive
/hello/i.test('HELLO');     // true

// g = global (find all matches)
'hello hello'.match(/hello/g);   // ["hello", "hello"]
'hello hello'.match(/hello/);    // ["hello"] (only first)

// m = multiline (^ and $ match line breaks)
const text = 'Line 1\nLine 2';
text.match(/^Line/gm);      // ["Line", "Line"]
text.match(/^Line/g);       // ["Line"] (only first line)

// s = dotall (. matches newlines)
'hello\nworld'.match(/.+/s);    // ["hello\nworld"]
'hello\nworld'.match(/.+/);     // ["hello"]

// u = unicode
/\u{1F600}/u.test('😀');   // true

Replace with Functions

// Replace with callback
const text = 'Price: $19.99 and $5.50';
const doubled = text.replace(/\$(\d+\.\d+)/g, (match, price) => {
    return '$' + (parseFloat(price) * 2).toFixed(2);
});
console.log(doubled); // "Price: $39.98 and $11.00"

// Capitalize words
const title = 'hello world'.replace(/\b\w/g, char => char.toUpperCase());
console.log(title); // "Hello World"

// Mask email
const email = 'user@example.com'.replace(
    /^(.{2})(.*)(@.*)$/,
    (match, start, middle, end) => start + '*'.repeat(middle.length) + end
);
console.log(email); // "us****@example.com"

Test and Validate

// test() - returns boolean
/\d+/.test('123');        // true
/\d+/.test('abc');        // false

// match() - returns array or null
'hello 123'.match(/\d+/);  // ["123"]
'hello'.match(/\d+/);      // null

// exec() - returns match object (reusable)
const regex = /\d+/g;
regex.exec('123 456');     // ["123"]
regex.exec('123 456');     // ["456"]
regex.exec('123 456');     // null (reset)

// matchAll() - iterator (requires g flag)
const text = 'hello 123 world 456';
const matches = [...text.matchAll(/(\w+) (\d+)/g)];
matches.forEach(match => {
    console.log(match[1], match[2]); // "hello" "123", "world" "456"
});

Real-World Examples

HTML Tag Removal

function stripHtml(html) {
    return html.replace(/<[^>]*>/g, '');
}

stripHtml('<p>Hello <b>world</b></p>'); // "Hello world"

// Keep text inside tags
function extractText(html) {
    return html.replace(/<[^>]*>/g, '').trim();
}

Extract Hashtags

const text = 'Love this! #coding #javascript #webdev';
const hashtags = text.match(/#\w+/g);
console.log(hashtags); // ["#coding", "#javascript", "#webdev"]

// Without the #
const tags = text.match(/#(\w+)/g).map(tag => tag.slice(1));
console.log(tags); // ["coding", "javascript", "webdev"]

URL Query Parameters

const url = 'https://example.com?id=123&name=John&age=30';

// Extract all parameters
const params = {};
url.replace(/[?&]([^=]+)=([^&]*)/g, (match, key, value) => {
    params[key] = value;
});
console.log(params); // { id: "123", name: "John", age: "30" }

// Or use URLSearchParams
const urlObj = new URL(url);
const params = Object.fromEntries(urlObj.searchParams);

Markdown Links

// Convert markdown links to HTML
const markdown = 'Check [this link](https://example.com) out';
const html = markdown.replace(
    /\[([^\]]+)\]\(([^\)]+)\)/g,
    '<a href="$2">$1</a>'
);
console.log(html);
// "Check <a href="https://example.com">this link</a> out"

Extract Code Blocks

const text = 'Code: `const x = 5` and `const y = 10`';
const code = text.match(/`([^`]+)`/g);
console.log(code); // ["`const x = 5`", "`const y = 10`"]

// Without backticks
const extracted = text.match(/`([^`]+)`/g).map(c => c.slice(1, -1));
console.log(extracted); // ["const x = 5", "const y = 10"]

Performance Tips

// BAD - Catastrophic backtracking
const badRegex = /(a+)+b/;
badRegex.test('aaaaaaaaaaaaaaaaaaaaaaaac'); // Takes forever!

// GOOD - Avoid nested quantifiers
const goodRegex = /a+b/;

// BAD - Unnecessary captures
const regex1 = /(\d+)/g;

// GOOD - Non-capturing groups when you don't need capture
const regex2 = /(?:\d+)/g;

// Reuse regex objects
const regex = /\d+/g;
// regex.test(), regex.test() ... (reset with regex.lastIndex = 0)

Regex Testing Tools

regex101.com - Best tool for testing:

  • Visual explanation of regex
  • Match highlighting
  • Quick reference
  • Multiple flavors (JS, Python, etc.)

regexr.com - Visual regex builder:

  • Interactive playground
  • Cheat sheet
  • Community patterns

When NOT to Use Regex

// Simple checks - use string methods
'hello'.startsWith('he');     // Better than /^he/.test('hello')
'hello'.includes('ll');        // Better than /ll/.test('hello')
'hello'.endsWith('lo');        // Better than /lo$/.test('hello')

// Complex parsing - use proper parser
// DON'T parse HTML with regex
// DON'T parse JSON with regex
// DON'T parse programming languages with regex

Quick Reference

// Anchors
^       Start of string
$       End of string
\b      Word boundary

// Character classes
\d      Digit [0-9]
\w      Word character [a-zA-Z0-9_]
\s      Whitespace [ \t\n\r]
.       Any character (except newline)

// Quantifiers
*       0 or more
+       1 or more
?       0 or 1
{n}     Exactly n
{n,}    n or more
{n,m}   Between n and m

// Groups
(...)   Capture group
(?:...) Non-capturing group
(?=...) Lookahead
(?!...) Negative lookahead

// Character sets
[abc]   Any of a, b, or c
[^abc]  Not a, b, or c
[a-z]   Any lowercase letter
[A-Z]   Any uppercase letter
[0-9]   Any digit

The Bottom Line

You don't need to master regex. Just learn these 10 patterns and you'll solve 90% of real problems.

Use regex101.com to test and understand patterns. It explains every part visually.

Named groups make regex readable. Use (?<name>...) to label captures.

Don't parse HTML or JSON with regex. Use proper parsers.

Test edge cases - regex breaks on unexpected input. Validate thoroughly.

I avoided regex for years because it looked scary. Then I learned 10 patterns. Now I use them daily. Copy these patterns, test them, adjust for your needs. That's how everyone learns regex.