JavaScript Regular Expressions (RegExp)
Master regular expressions, pattern matching, and text processing techniques for advanced string manipulation and validation. This is a foundational concept in programming and web interactivity that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world JavaScript experience. Take your time with each section and practice the examples
RegExp Fundamentals
Regular expressions are powerful tools for pattern matching and text manipulation. They provide a concise and flexible way to search, replace, and validate text data in JavaScript applications.. This is an essential concept that every JavaScript developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Creating Regular Expressions
// Creating regular expressions
// Literal syntax
const pattern1 = /hello/;
const pattern2 = /hello/i; // Case insensitive
// Constructor syntax
const pattern3 = new RegExp('hello');
const pattern4 = new RegExp('hello', 'i');
// Basic patterns
const wordPattern = /\b\w+\b/; // Word boundaries
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const phonePattern = /^\+?[1-9]\d{1,14}$/;
// Character classes
const digitPattern = /\d/; // Any digit
const wordCharPattern = /\w/; // Word character
const whitespacePattern = /\s/; // Whitespace
const nonDigitPattern = /\D/; // Non-digit
const nonWordPattern = /\W/; // Non-word character
const nonWhitespacePattern = /\S/; // Non-whitespace
// Quantifiers
const zeroOrMore = /a*/; // Zero or more 'a'
const oneOrMore = /a+/; // One or more 'a'
const zeroOrOne = /a?/; // Zero or one 'a'
const exactCount = /a{3}/; // Exactly 3 'a'
const rangeCount = /a{2,4}/; // 2 to 4 'a'
const atLeastCount = /a{2,}/; // At least 2 'a'
// Anchors
const startAnchor = /^hello/; // Starts with 'hello'
const endAnchor = /world$/; // Ends with 'world'
const wordBoundary = /\bword\b/; // Word boundary
// Groups and capturing
const groupPattern = /(\d{3})-(\d{3})-(\d{4})/; // Phone number groups
const nonCapturingGroup = /(?:\d{3})-(\d{3})-(\d{4})/; // Non-capturing group
// Alternation
const orPattern = /cat|dog|bird/; // cat or dog or bird
// Flags
const globalFlag = /hello/g; // Global search
const caseInsensitiveFlag = /hello/i; // Case insensitive
const multilineFlag = /^hello/m; // Multiline
const stickyFlag = /hello/y; // Sticky
const unicodeFlag = /hello/u; // Unicode
// Test method
console.log(/hello/.test('hello world')); // true
console.log(/hello/.test('world')); // false
// Exec method
const match = /(\d{3})-(\d{3})-(\d{4})/.exec('123-456-7890');
console.log(match); // ['123-456-7890', '123', '456', '7890']
// String methods with RegExp
const text = 'Hello world, hello universe';
console.log(text.match(/hello/gi)); // ['Hello', 'hello']
console.log(text.replace(/hello/gi, 'hi')); // 'Hi world, hi universe'
console.log(text.search(/world/)); // 6
console.log(text.split(/\s+/)); // ['Hello', 'world,', 'hello', 'universe']Advanced RegExp Patterns
// Advanced RegExp patterns
// Email validation
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// Password validation (8+ chars, 1 uppercase, 1 lowercase, 1 digit)
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/;
// URL validation
const urlRegex = /^https?:\/\/([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?$/;
// Credit card validation
const creditCardRegex = /^(\d{4}[\s-]?){4}$/;
// Date validation (YYYY-MM-DD)
const dateRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
// Phone number validation
const phoneRegex = /^\+?1?[-.\s]?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})$/;
// Social security Number validation
const ssnRegex = /^\d{3}-\d{2}-\d{4}$/;
// IP address validation
const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
// HTML tag matching
const htmlTagRegex = /<[^>]*>/g;
// CSS selector validation
const cssSelectorRegex = /^[.#]?[a-zA-Z][a-zA-Z0-9_-]*$/;
// Function to validate patterns
function validatePattern(text, pattern) {
return pattern.test(text);
}
// Test validation functions
console.log(validatePattern('user@example.com', emailRegex)); // true
console.log(validatePattern('weak', passwordRegex)); // false
console.log(validatePattern('https://example.com', urlRegex)); // true
console.log(validatePattern('1234-5678-9012-3456', creditCardRegex)); // true
// RegExp with Unicode
const unicodeRegex = /\p{L}/u; // Any letter
const emojiRegex = /\p{Emoji}/u; // Any emoji
const currencyRegex = /\p{Sc}/u; // Any currency symbol
// Lookahead and lookbehind
const positiveLookahead = /\d(?=\s)/; // Digit followed by space
const negativeLookahead = /\d(?!\s)/; // Digit not followed by space
const positiveLookbehind = /(?<=\$)\d/; // Digit preceded by dollar sign
const negativeLookbehind = /(?<!\$)\d/; // Digit not preceded by dollar sign
// Named capture groups
const namedGroupRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const dateMatch = namedGroupRegex.exec('2023-12-25');
console.log(dateMatch.groups); // { year: '2023', month: '12', day: '25' }
// RegExp with template literals
function createPattern(domain) {
return new RegExp(`^[a-zA-Z0-9._%+-]+@${domain.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`);
}
const gmailPattern = createPattern('gmail.com');
console.log(gmailPattern.test('user@gmail.com')); // truePractice Exercise: RegExp
// Exercise: Build a Text Processor with RegExp
class TextProcessor {
constructor() {
this.patterns = new Map();
this.initializePatterns();
}
initializePatterns() {
this.patterns.set('email', /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g);
this.patterns.set('phone', /\+?1?[-.\s]?\(?([0-9]{3})\)?[-.\s]?([0-9]{3})[-.\s]?([0-9]{4})/g);
this.patterns.set('url', /https?:\/\/([\w-]+\.)+[\w-]+(\/[\w-./?%&=]*)?/g);
this.patterns.set('date', /\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])/g);
this.patterns.set('creditCard', /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g);
}
extract(text, type) {
const pattern = this.patterns.get(type);
if (!pattern) {
throw new Error(`Unknown pattern type: ${type}`);
}
return text.match(pattern) || [];
}
mask(text, type, maskChar = '*') {
const pattern = this.patterns.get(type);
if (!pattern) {
throw new Error(`Unknown pattern type: ${type}`);
}
return text.replace(pattern, (match) => {
if (type === 'email') {
const [local, domain] = match.split('@');
return `${local.charAt(0)}${maskChar.repeat(local.length - 2)}${local.charAt(local.length - 1)}@${domain}`;
} else if (type === 'phone') {
return match.replace(/\d/g, maskChar);
} else if (type === 'creditCard') {
return match.replace(/\d(?=\d{4})/g, maskChar);
}
return maskChar.repeat(match.length);
});
}
validate(text, type) {
const pattern = this.patterns.get(type);
if (!pattern) {
throw new Error(`Unknown pattern type: ${type}`);
}
return pattern.test(text);
}
replace(text, type, replacement) {
const pattern = this.patterns.get(type);
if (!pattern) {
throw new Error(`Unknown pattern type: ${type}`);
}
return text.replace(pattern, replacement);
}
addPattern(name, pattern) {
this.patterns.set(name, pattern);
}
}
// Exercise: Build a RegExp Builder
class RegExpBuilder {
constructor() {
this.parts = [];
this.flags = '';
}
start() {
this.parts.push('^');
return this;
}
end() {
this.parts.push('$');
return this;
}
digit() {
this.parts.push('\d');
return this;
}
letter() {
this.parts.push('[a-zA-Z]');
return this;
}
word() {
this.parts.push('\w');
return this;
}
whitespace() {
this.parts.push('\s');
return this;
}
literal(text) {
this.parts.push(text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
return this;
}
oneOrMore() {
this.parts.push('+');
return this;
}
zeroOrMore() {
this.parts.push('*');
return this;
}
zeroOrOne() {
this.parts.push('?');
return this;
}
exactly(count) {
this.parts.push(`{${count}}`);
return this;
}
between(min, max) {
this.parts.push(`{${min},${max}}`);
return this;
}
or(...alternatives) {
this.parts.push(`(${alternatives.join('|')})`);
return this;
}
group(content) {
this.parts.push(`(${content})`);
return this;
}
nonCapturingGroup(content) {
this.parts.push(`(?:\${content})`);
return this;
}
caseInsensitive() {
this.flags += 'i';
return this;
}
global() {
this.flags += 'g';
return this;
}
multiline() {
this.flags += 'm';
return this;
}
build() {
const pattern = this.parts.join('');
return new RegExp(pattern, this.flags);
}
}
// Test the exercises
const processor = new TextProcessor();
const sampleText = `
Contact us at john@example.com or call +1-555-123-4567.
Visit https://example.com for more information.
Credit card: 1234-5678-9012-3456
Date: 2023-12-25
`;
console.log('Extracted emails:', processor.extract(sampleText, 'email'));
console.log('Extracted phones:', processor.extract(sampleText, 'phone'));
console.log('Masked text:', processor.mask(sampleText, 'email'));
const builder = new RegExpBuilder();
const emailPattern = builder
.start()
.word()
.zeroOrMore()
.literal('@')
.word()
.oneOrMore()
.literal('.')
.letter()
.between(2, 4)
.end()
.caseInsensitive()
.build();
console.log('Built pattern:', emailPattern);
console.log('Email validation:', emailPattern.test('user@example.com'));