Advertisement

Regular Expressions Mastery: From Beginner to Expert

October 25, 202535 min readTutorial

Regular expressions (regex) are powerful tools for pattern matching and text manipulation. Whether you're validating form inputs, parsing data, or transforming text, mastering regex will make you a more efficient developer.

What Are Regular Expressions?

Regular expressions are sequences of characters that define search patterns. They're used in almost every programming language for tasks like validation, searching, and text manipulation. Think of them as a specialized language for describing text patterns.

Basic Syntax

In JavaScript, regex patterns are enclosed in forward slashes:

// Basic regex pattern
const pattern = /hello/;

// With flags
const patternWithFlags = /hello/gi;

// Using RegExp constructor
const dynamicPattern = new RegExp('hello', 'gi');

Regex Flags

Flags modify how the pattern matching works:

  • g - Global: Find all matches, not just the first
  • i - Case insensitive: Match regardless of case
  • m - Multiline: ^ and $ match line starts/ends
  • s - Dot all: . matches newline characters
  • u - Unicode: Enable full unicode support
  • y - Sticky: Match from lastIndex position
const text = 'Hello World, hello universe';

// Without flags
console.log(text.match(/hello/));
// Output: ['Hello'] (first match only, case matters)

// With 'g' flag
console.log(text.match(/hello/g));
// Output: null (case matters, no lowercase 'hello')

// With 'gi' flags
console.log(text.match(/hello/gi));
// Output: ['Hello', 'hello'] (all matches, case insensitive)

Character Classes

Basic Character Classes

PatternDescriptionExample
.Any character except newline/c.t/ matches "cat", "cot"
\dAny digit (0-9)/\d+/ matches "123"
\DAny non-digit/\D+/ matches "abc"
\wWord character (a-z, A-Z, 0-9, _)/\w+/ matches "hello_123"
\WNon-word character/\W+/ matches "!@#"
\sWhitespace (space, tab, newline)/\s+/ matches spaces
\SNon-whitespace/\S+/ matches "hello"

Custom Character Sets

// Match specific characters
const vowels = /[aeiou]/gi;
console.log('hello'.match(vowels));
// Output: ['e', 'o']

// Match ranges
const lowerCase = /[a-z]/g;
const upperCase = /[A-Z]/g;
const alphaNumeric = /[a-zA-Z0-9]/g;

// Negated sets (NOT these characters)
const notVowels = /[^aeiou]/gi;
console.log('hello'.match(notVowels));
// Output: ['h', 'l', 'l']

Quantifiers

Quantifiers specify how many times a pattern should match:

QuantifierDescriptionExample
*0 or more times/ab*c/ matches "ac", "abc", "abbc"
+1 or more times/ab+c/ matches "abc", "abbc"
?0 or 1 time (optional)/colou?r/ matches "color", "colour"
{n}Exactly n times/\d{3}/ matches "123"
{n,}n or more times/\d{2,}/ matches "12", "123"
{n,m}Between n and m times/\d{2,4}/ matches "12", "123"
// Phone number pattern (XXX-XXX-XXXX)
const phonePattern = /\d{3}-\d{3}-\d{4}/;
console.log(phonePattern.test('123-456-7890')); // true

// ZIP code (5 or 9 digits)
const zipPattern = /^\d{5}(-\d{4})?$/;
console.log(zipPattern.test('12345')); // true
console.log(zipPattern.test('12345-6789')); // true

// Password (8-16 chars, must include number)
const passwordPattern = /^(?=.*\d).{8,16}$/;
console.log(passwordPattern.test('password123')); // true

Anchors and Boundaries

AnchorDescriptionExample
^Start of string/line/^Hello/ matches "Hello world"
$End of string/line/world$/ matches "Hello world"
\bWord boundary/\bcat\b/ matches "cat" not "catch"
// Must start with uppercase letter
const startsWithUpper = /^[A-Z]/;
console.log(startsWithUpper.test('Hello')); // true
console.log(startsWithUpper.test('hello')); // false

// Must end with punctuation
const endsWithPunc = /[.!?]$/;
console.log(endsWithPunc.test('Hello!')); // true

// Whole word match
const wholeWord = /\bcat\b/;
console.log('the cat sat'.match(wholeWord)); // matches
console.log('catch it'.match(wholeWord)); // no match

Groups and Capturing

Capturing Groups

// Extract parts of a date
const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = '2025-10-25'.match(datePattern);

console.log(match[0]); // "2025-10-25" (full match)
console.log(match[1]); // "2025" (year)
console.log(match[2]); // "10" (month)
console.log(match[3]); // "25" (day)

// Named capturing groups
const namedPattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const namedMatch = '2025-10-25'.match(namedPattern);

console.log(namedMatch.groups.year);  // "2025"
console.log(namedMatch.groups.month); // "10"
console.log(namedMatch.groups.day);   // "25"

Non-Capturing Groups

// Non-capturing group (?:...)
const pattern = /(?:Mr|Mrs|Ms)\.\s+(\w+)/;
const match = 'Mr. Smith'.match(pattern);

console.log(match[0]); // "Mr. Smith"
console.log(match[1]); // "Smith" (only captured group)

Common Regex Patterns

Email Validation

// Basic email pattern
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

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

function validateEmail(email) {
  return strictEmail.test(email);
}

console.log(validateEmail('user@example.com'));     // true
console.log(validateEmail('invalid.email'));        // false
console.log(validateEmail('user@domain'));          // false

Phone Number Validation

// US phone number patterns
const usPhone1 = /^\d{3}-\d{3}-\d{4}$/;           // 123-456-7890
const usPhone2 = /^\(\d{3}\)\s?\d{3}-\d{4}$/; // (123) 456-7890
const usPhone3 = /^\d{10}$/;                        // 1234567890

// Flexible phone pattern
const phonePattern = /^[\d\s()+-]+$/;

function validatePhone(phone) {
  // Remove all non-digits
  const digits = phone.replace(/\D/g, '');

  // Check if 10 digits
  return digits.length === 10;
}

console.log(validatePhone('(123) 456-7890'));  // true
console.log(validatePhone('123-456-7890'));    // true
console.log(validatePhone('123 456 7890'));    // true

URL Validation

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

function validateURL(url) {
  return urlPattern.test(url);
}

console.log(validateURL('https://example.com'));           // true
console.log(validateURL('http://www.example.com/path'));   // true
console.log(validateURL('not-a-url'));                     // false

Password Strength

// Strong password requirements:
// - At least 8 characters
// - At least one uppercase letter
// - At least one lowercase letter
// - At least one number
// - At least one special character

function validateStrongPassword(password) {
  const minLength = /.{8,}/;
  const hasUpper = /[A-Z]/;
  const hasLower = /[a-z]/;
  const hasNumber = /\d/;
  const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/;

  return (
    minLength.test(password) &&
    hasUpper.test(password) &&
    hasLower.test(password) &&
    hasNumber.test(password) &&
    hasSpecial.test(password)
  );
}

// Or use lookaheads in a single regex
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;

console.log(strongPassword.test('Weak123'));           // false
console.log(strongPassword.test('Strong@Pass123'));    // true

JavaScript Regex Methods

String Methods

const text = 'The quick brown fox jumps over the lazy dog';

// match() - returns array of matches
console.log(text.match(/the/gi));
// Output: ['The', 'the']

// search() - returns index of first match
console.log(text.search(/fox/));
// Output: 16

// replace() - replaces matches
console.log(text.replace(/the/gi, 'a'));
// Output: "a quick brown fox jumps over a lazy dog"

// replaceAll() - replaces all matches (ES2021)
console.log(text.replaceAll(/the/gi, 'a'));

// split() - splits string by pattern
console.log('a,b;c:d'.split(/[,;:]/));
// Output: ['a', 'b', 'c', 'd']

RegExp Methods

const pattern = /\d+/g;
const text = 'I have 2 cats and 3 dogs';

// test() - returns true/false
console.log(/\d/.test(text));
// Output: true

// exec() - returns match details
let match;
while ((match = pattern.exec(text)) !== null) {
  console.log(`Found ${match[0]} at index ${match.index}`);
}
// Output:
// Found 2 at index 7
// Found 3 at index 18

Advanced Techniques

Lookahead and Lookbehind

// Positive lookahead (?=...)
// Match digits followed by "px"
const pxPattern = /\d+(?=px)/;
console.log('10px 20em 30px'.match(pxPattern));
// Output: ['10'] (doesn't include 'px')

// Negative lookahead (?!...)
// Match digits NOT followed by "px"
const notPxPattern = /\d+(?!px)/;
console.log('10px 20em 30px'.match(notPxPattern));
// Output: ['2'] (from '20em')

// Positive lookbehind (?<=...)
// Match digits preceded by "$"
const pricePattern = /(?<=\$)\d+/;
console.log('$100 and €50'.match(pricePattern));
// Output: ['100']

// Negative lookbehind (?<!...)
// Match digits NOT preceded by "$"
const notPricePattern = /(?<!\$)\d+/;
console.log('$100 and 50'.match(notPricePattern));
// Output: ['0', '0', '5', '0'] (individual digits)

Real-World Examples

Credit Card Validation

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

  // Check if 13-19 digits
  const pattern = /^\d{13,19}$/;

  if (!pattern.test(cleaned)) {
    return false;
  }

  // Luhn algorithm check
  let sum = 0;
  let isEven = false;

  for (let i = cleaned.length - 1; i >= 0; i--) {
    let digit = parseInt(cleaned[i]);

    if (isEven) {
      digit *= 2;
      if (digit > 9) digit -= 9;
    }

    sum += digit;
    isEven = !isEven;
  }

  return sum % 10 === 0;
}

console.log(validateCreditCard('4532-1488-0343-6467')); // true (Visa)
console.log(validateCreditCard('1234-5678-9012-3456')); // false

Extract Data from Text

// Extract all email addresses from text
function extractEmails(text) {
  const emailPattern = /[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
  return text.match(emailPattern) || [];
}

const text = `Contact us at support@example.com or sales@example.com`;
console.log(extractEmails(text));
// Output: ['support@example.com', 'sales@example.com']

// Extract hashtags from social media post
function extractHashtags(text) {
  const hashtagPattern = /#[a-zA-Z0-9_]+/g;
  return text.match(hashtagPattern) || [];
}

const post = 'Learning #JavaScript and #WebDev is fun! #coding';
console.log(extractHashtags(post));
// Output: ['#JavaScript', '#WebDev', '#coding']

Performance Tips

Best Practices:

  • ✅ Use specific patterns instead of broad ones
  • ✅ Compile regex once and reuse
  • ✅ Use non-capturing groups when you don't need the match
  • ✅ Avoid excessive backtracking with greedy quantifiers
  • ❌ Don't use regex for simple string operations
  • ❌ Avoid nested quantifiers like (a+)+

Conclusion

Regular expressions are an essential tool in every developer's toolkit. While they can seem intimidating at first, with practice and understanding of the core concepts, you'll find them invaluable for text processing, validation, and data extraction tasks.

Start with simple patterns and gradually build complexity as you become more comfortable. Remember to test your regex thoroughly and consider edge cases in your validation logic.

Try Our Regex Playground

Test and build regex patterns with live matching and visual highlighting!

Try Regex Playground →
Advertisement