Regex
Regular expressions (regex) are patterns used to match character combinations in strings.
Basic Regex Syntax
javascript// Creating regex patterns const regex1 = /hello/; // Literal notation const regex2 = new RegExp('hello'); // Constructor const regex3 = new RegExp('hello', 'i'); // With flags // Basic matching const text = 'Hello World'; console.log(/hello/i.test(text)); // true (case insensitive) console.log(text.match(/hello/i)); // ['Hello'] // Flags const pattern = /hello/gi; // g = global, i = case insensitive // m = multiline, s = dotall, u = unicode, y = sticky
Character Classes and Quantifiers
javascript// Character classes const digitPattern = /\d/; // Matches any digit (0-9) const wordPattern = /\w/; // Matches word characters (a-z, A-Z, 0-9, _) const spacePattern = /\s/; // Matches whitespace // Negated character classes const nonDigit = /\D/; // Matches non-digits const nonWord = /\W/; // Matches non-word characters const nonSpace = /\S/; // Matches non-whitespace // Custom character classes const vowels = /[aeiou]/i; // Matches any vowel const consonants = /[^aeiou]/i; // Matches any consonant const hexDigit = /[0-9a-fA-F]/; // Matches hex digits // Quantifiers const oneOrMore = /\d+/; // One or more digits const zeroOrMore = /\d*/; // Zero or more digits const zeroOrOne = /\d?/; // Zero or one digit const exactly3 = /\d{3}/; // Exactly 3 digits const between2and4 = /\d{2,4}/; // Between 2 and 4 digits const atLeast2 = /\d{2,}/; // At least 2 digits // Examples console.log('123'.match(/\d+/)); // ['123'] console.log('abc123def'.match(/\d+/)); // ['123'] console.log('phone: 555-1234'.match(/\d{3}-\d{4}/)); // ['555-1234']
Anchors and Boundaries
javascript// Anchors const startOfString = /^hello/; // Matches 'hello' at start const endOfString = /world$/; // Matches 'world' at end const exactMatch = /^hello$/; // Matches exactly 'hello' // Word boundaries const wordBoundary = /\bhello\b/; // Matches 'hello' as whole word const nonWordBoundary = /\Bhello\B/; // Matches 'hello' within word // Examples console.log('hello world'.match(/^hello/)); // ['hello'] console.log('say hello'.match(/^hello/)); // null console.log('hello there'.match(/hello$/)); // null console.log('hello'.match(/^hello$/)); // ['hello'] console.log('hello world'.match(/\bhello\b/)); // ['hello'] console.log('othello game'.match(/\bhello\b/)); // null
Groups and Capturing
javascript// Capturing groups const namePattern = /(\w+)\s+(\w+)/; // First name and last name const fullName = 'John Doe'; const match = fullName.match(namePattern); console.log(match[0]); // 'John Doe' (full match) console.log(match[1]); // 'John' (first group) console.log(match[2]); // 'Doe' (second group) // Named capturing groups const emailPattern = /(?<username>\w+)@(?<domain>\w+\.\w+)/; const email = 'user@example.com'; const emailMatch = email.match(emailPattern); console.log(emailMatch.groups.username); // 'user' console.log(emailMatch.groups.domain); // 'example.com' // Non-capturing groups const nonCapturing = /(?:Mr|Mrs|Ms)\.\s+(\w+)/; const title = 'Mr. Smith'; const titleMatch = title.match(nonCapturing); console.log(titleMatch[1]); // 'Smith' (only one capturing group) // Alternation const colorPattern = /(red|green|blue)/; console.log('I like red'.match(colorPattern)); // ['red', 'red']
Common Validation Patterns
javascript// Email validation function isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } // Phone number validation function isValidPhone(phone) { const phoneRegex = /^\+?[1-9]\d{1,14}$/; // International format const usPhoneRegex = /^$$?([0-9]{3})$$?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/; return phoneRegex.test(phone) || usPhoneRegex.test(phone); } // URL validation function isValidUrl(url) { const urlRegex = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&=]*)$/; return urlRegex.test(url); } // Password strength function validatePassword(password) { const minLength = /.{8,}/; // At least 8 characters const hasUpper = /[A-Z]/; // At least one uppercase const hasLower = /[a-z]/; // At least one lowercase const hasDigit = /\d/; // At least one digit const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/; // At least one special char return { minLength: minLength.test(password), hasUpper: hasUpper.test(password), hasLower: hasLower.test(password), hasDigit: hasDigit.test(password), hasSpecial: hasSpecial.test(password) }; } // Credit card validation function isValidCreditCard(cardNumber) { const visa = /^4[0-9]{12}(?:[0-9]{3})?$/; const mastercard = /^5[1-5][0-9]{14}$/; const amex = /^3[47][0-9]{13}$/; return visa.test(cardNumber) || mastercard.test(cardNumber) || amex.test(cardNumber); } console.log(isValidEmail('user@example.com')); // true console.log(isValidPhone('+1234567890')); // true console.log(validatePassword('MyPass123!')); // All true
String Methods with Regex
javascriptconst text = 'The quick brown fox jumps over the lazy dog'; // test() - returns boolean console.log(/fox/.test(text)); // true // match() - returns array of matches console.log(text.match(/\b\w{4}\b/g)); // ['over', 'lazy'] // matchAll() - returns iterator of all matches const matches = [...text.matchAll(/\b(\w{4})\b/g)]; console.log(matches[0][1]); // 'over' // search() - returns index of first match console.log(text.search(/fox/)); // 16 // replace() - replace matches console.log(text.replace(/fox/, 'cat')); // Replace first occurrence console.log(text.replace(/\b\w{3}\b/g, 'XXX')); // Replace all 3-letter words // replaceAll() - replace all matches console.log(text.replaceAll(/\b\w{3}\b/g, 'XXX')); // split() - split string by regex console.log(text.split(/\s+/)); // Split by whitespace console.log('a1b2c3d'.split(/\d/)); // ['a', 'b', 'c', 'd']
Advanced Regex Features
javascript// Lookahead and lookbehind const passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/; // Positive lookahead: (?=.*[a-z]) - must contain lowercase // Negative lookahead: (?!.*[a-z]) - must not contain lowercase const lookbehindPattern = /(?<=\$)\d+/; // Matches digits after $ const negativeLookbehind = /(?<!\$)\d+/; // Matches digits not after $ // Greedy vs non-greedy quantifiers const html = '<div>Hello</div><span>World</span>'; console.log(html.match(/<.*>/)); // ['<div>Hello</div><span>World</span>'] - greedy console.log(html.match(/<.*?>/)); // ['<div>'] - non-greedy // Backreferences const duplicateWords = /(\b\w+)\s+\1\b/; // Matches repeated words console.log('This is is a test'.match(duplicateWords)); // ['is is', 'is'] // Replace with backreferences const swapNames = 'John Doe'.replace(/(\w+)\s+(\w+)/, '$2, $1'); console.log(swapNames); // 'Doe, John'
Practical Examples
javascript// Extract data from text function extractPhoneNumbers(text) { const phoneRegex = /$$?([0-9]{3})$$?[-. ]?([0-9]{3})[-. ]?([0-9]{4})/g; return [...text.matchAll(phoneRegex)].map(match => match[0]); } // Clean and format text function cleanText(text) { return text .replace(/\s+/g, ' ') // Replace multiple spaces with single space .replace(/[^\w\s.,!?-]/g, '') // Remove special characters except basic punctuation .trim(); } // Parse CSV with regex function parseCSV(csvText) { const lines = csvText.split('\n'); const csvRegex = /,(?=(?:[^"]*"[^"]*")*[^"]*$)/; return lines.map(line => { return line.split(csvRegex).map(field => { return field.replace(/^"|"$/g, '').replace(/""/g, '"'); }); }); } // Highlight search terms function highlightText(text, searchTerm) { const regex = new RegExp(`(${searchTerm})`, 'gi'); return text.replace(regex, '<mark>$1</mark>'); } // Validate and format input function formatInput(input, type) { switch (type) { case 'phone': const cleaned = input.replace(/\D/g, ''); return cleaned.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3'); case 'ssn': const ssnCleaned = input.replace(/\D/g, ''); return ssnCleaned.replace(/(\d{3})(\d{2})(\d{4})/, '$1-$2-$3'); case 'creditCard': const ccCleaned = input.replace(/\D/g, ''); return ccCleaned.replace(/(\d{4})/g, '$1 ').trim(); default: return input; } } // Usage examples const text = 'Call me at (555) 123-4567 or 555.987.6543'; console.log(extractPhoneNumbers(text)); // ['(555) 123-4567', '555.987.6543'] console.log(cleanText(' Hello, world!!! @#$ ')); // 'Hello, world!' console.log(highlightText('JavaScript is awesome', 'script')); // 'Java<mark>Script</mark> is awesome' console.log(formatInput('5551234567', 'phone')); // '(555) 123-4567'
Performance and Best Practices
javascript// Compile regex once for reuse const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; function validateEmails(emails) { return emails.filter(email => emailRegex.test(email)); } // Avoid catastrophic backtracking // Bad: /(a+)+b/ - can cause exponential time complexity // Good: /a+b/ - linear time complexity // Use specific patterns instead of .* when possible // Bad: /.*@.*\..*/ - too general // Good: /[\w.-]+@[\w.-]+\.[a-zA-Z]{2,}/ - more specific // Test regex performance function testRegexPerformance() { const text = 'test@example.com'; const iterations = 100000; console.time('Regex test'); for (let i = 0; i < iterations; i++) { emailRegex.test(text); } console.timeEnd('Regex test'); } function createSearchRegex(searchTerm) { const escaped = escapeRegex(searchTerm); return new RegExp(escaped, 'gi'); } // Usage const userInput = 'Hello (world)'; const searchRegex = createSearchRegex(userInput); console.log('Hello (world) test'.match(searchRegex)); // ['Hello (world)']