Regular expressions (regex) are one of the most powerful tools for text processing and pattern matching. Despite their intimidating appearance, mastering regex can dramatically improve your coding efficiency and text manipulation capabilities.
In this guide, we'll demystify regex, show you practical examples, and help you become proficient with pattern matching.
🔍 What are regular expressions?
Regular expressions are patterns used to match character combinations in strings. They're like a search language that describes what you're looking for in text.
Basic syntax
const regex = /pattern/flags;
const result = text.match(regex);
Real example
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const isValid = email.test("user@example.com"); // true
🧩 Essential regex components
Character classes
Pattern | Matches | Example |
. | Any character except newline | /a.c/ matches "abc", "axc" |
\d | Any digit (0-9) | /\d+/ matches "123" |
\w | Word characters (a-z, A-Z, 0-9, _) | /\w+/ matches "hello_123" |
\s | Whitespace characters | /\s+/ matches spaces, tabs |
[abc] | Any character in brackets | /[aeiou]/ matches vowels |
[a-zA-Z] | Any letter (upper or lowercase) | /[a-zA-Z]+/g matches "Hello" |
[^abc] | Any character NOT in brackets | /[^0-9]/ matches non-digits |
Quantifiers
Pattern | Meaning | Example |
* | Zero or more | /ab*/ matches "a", "ab", "abbb" |
+ | One or more | /ab+/ matches "ab", "abbb" (not "a") |
? | Zero or one | /colou?r/ matches "color", "colour" |
{n} | Exactly n times | /\d{3}/ matches exactly 3 digits |
{n,m} | Between n and m times | /\d{2,4}/ matches 2-4 digits |
Anchors
Pattern | Meaning | Example |
^ | Start of string/line | /^Hello/ matches "Hello world" |
$ | End of string/line | /world$/ matches "Hello world" |
\b | Word boundary | /\bcat\b/ matches "cat" not "catch" |
🎯 Common use cases & solutions
Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const email = "user@example.com";
console.log(emailRegex.test(email)); // true
Phone number extraction
const phoneRegex = /\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/g;
const text = "Call me at (555) 123-4567 or 555.987.6543";
const phones = text.match(phoneRegex);
// ["(555) 123-4567", "555.987.6543"]
URL Matching
const urlRegex = /https?:\/\/[^\s]+/g;
const text = "Visit https://example.com or http://test.org";
const urls = text.match(urlRegex);
// ["https://example.com", "http://test.org"]
Password validation
// At least 8 chars, 1 uppercase, 1 lowercase, 1 digit
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/;
const password = "MyPass123";
console.log(strongPassword.test(password)); // true
🔧 Practical examples
Data cleaning
// Remove extra whitespace
const cleanText = text.replace(/\s+/g, ' ').trim();
// Extract numbers from string
const numbers = "Price: $29.99, Tax: $2.50".match(/\d+\.?\d*/g);
// ["29.99", "2.50"]
// Format phone numbers
const formatPhone = (phone) => {
return phone.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
};
HTML Tag removal
const stripHtml = (html) => {
return html.replace(/<[^>]*>/g, '');
};
const clean = stripHtml("<p>Hello <b>world</b>!</p>");
// "Hello world!"
Find and replace
// Replace multiple spaces with single space
const text = "Hello world there";
const cleaned = text.replace(/\s+/g, ' ');
// "Hello world there"
// Convert camelCase to kebab-case
const kebabCase = (str) => {
return str.replace(/([A-Z])/g, '-$1').toLowerCase();
};
⚙️ Regex flags
Flag | Purpose | Example |
g | Global (find all matches) | /cat/g finds all "cat" occurrences |
i | Case insensitive | /hello/i matches "Hello", "HELLO" |
m | Multiline | /^start/m matches "start" at line beginnings |
s | Dot matches newlines | /a.b/s matches "a\nb" |
const text = "Hello World, hello everyone";
const matches = text.match(/hello/gi); // ["Hello", "hello"]
🚀 Advanced patterns
Lookaheads and lookbehinds
// Positive lookahead: password with digit
const hasDigit = /^(?=.*\d).+$/;
// Negative lookahead: word not followed by "ing"
const notIng = /\b\w+(?!ing)\b/g;
// Positive lookbehind: digit after "$"
const afterDollar = /(?<=\$)\d+/g;
Capturing groups
const dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
const match = "2024-03-15".match(dateRegex);
// ["2024-03-15", "2024", "03", "15"]
const [full, year, month, day] = match;
Named groups
const nameRegex = /(?<first>\w+)\s+(?<last>\w+)/;
const match = "Marta Perez".match(nameRegex);
// match.groups.first = "Marta"
// match.groups.last = "Perez"
🛠️ Framework integration
Javascript
// String methods
"hello world".match(/\w+/g); // ["hello", "world"]
"hello world".replace(/\w+/g, 'hi'); // "hi hi"
"hello world".search(/world/); // 6
// RegExp methods
/\d+/.test("123abc"); // true
/(\w+)/g.exec("hello world"); // ["hello", "hello"]
Node.js file processing
const fs = require('fs');
const processLogFile = (filename) => {
const content = fs.readFileSync(filename, 'utf8');
const errors = content.match(/ERROR.*$/gm);
return errors || [];
};
React form validation
const validateInput = (value, pattern) => {
return pattern.test(value);
};
// Usage in component
const isValidEmail = validateInput(email, /^[^\s@]+@[^\s@]+\.[^\s@]+$/);
⚠️ Common pitfalls
Greedy vs non-greedy
// Greedy (matches as much as possible)
const greedy = /<.*>/g;
"<div>content</div>".match(greedy); // ["<div>content</div>"]
// Non-greedy (matches as little as possible)
const nonGreedy = /<.*?>/g;
"<div>content</div>".match(nonGreedy); // ["<div>", "</div>"]
Escaping special characters
// Wrong: trying to match literal dots
const wrong = /3.14/; // Matches "3X14" too
// Correct: escape the dot
const correct = /3\.14/; // Matches only "3.14"
// Escape function
const escapeRegex = (str) => {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
🔍 Testing and debugging
Online tools
- regex101.com - Interactive testing with explanations
- regexr.com - Visual regex builder
- regexpal.com - Simple testing interface
Testing in code
const testRegex = (pattern, tests) => {
tests.forEach(({ input, expected }) => {
const result = pattern.test(input);
console.log(`${input}: ${result === expected ? '✅' : '❌'}`);
});
};
testRegex(/^\d{3}-\d{2}-\d{4}$/, [
{ input: "123-45-6789", expected: true },
{ input: "123-456-789", expected: false }
]);
🎯 When to use regex
Perfect for:
- Input validation (emails, phones, passwords)
- Data extraction from text files
- Text cleaning and formatting
- Log file analysis
- Find and replace operations
Avoid for:
- HTML/XML parsing (use proper parsers)
- Complex nested structures
- When readability matters more than brevity
- Performance-critical loops (compile once, reuse)
✅ Best practices
- Keep it simple - Complex regex is hard to maintain
- Use comments for complex patterns
- Test thoroughly with edge cases
- Compile once for repeated use
- Consider alternatives for complex parsing
// Good: Clear and maintainable
const phoneRegex = /^\(\d{3}\) \d{3}-\d{4}$/;
// Bad: Overly complex
const badRegex = /^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$/;
🧠 Conclusion
Regular expressions are incredibly powerful for text processing and pattern matching. While they can seem intimidating at first, understanding the basic building blocks and common patterns will make you much more efficient at handling text data.
Start with simple patterns, practice with real examples, and gradually build up to more complex expressions. Remember: a readable regex that works is better than a clever one that nobody can understand.