DEV Community

Alex Chen
Alex Chen

Posted on

Regular Expressions Explained: The Visual Guide

Regular Expressions Explained: The Visual Guide

Regex doesn't have to be cryptic. Let me decode it for you.

What Is Regex?

Regex = pattern matching for text. Think "find and replace on steroids."

Text: "My email is alex@example.com and my phone is 555-123-4567"
Regex: \b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b
Match: alex@example.com
Enter fullscreen mode Exit fullscreen mode

The Core Syntax (Cheat Sheet)

Character Classes

.        Any character (except newline)
\d       Digit [0-9]
\D       Not a digit [^0-9]
\w       Word character [a-zA-Z0-9_]
\W       Not a word character
\s       Whitespace (space, tab, newline)
\S       Not whitespace

[abc]    Any of a, b, or c
[a-z]    Any lowercase letter
[0-9]    Any digit (same as \d)
[^abc]   NOT a, b, or c
Enter fullscreen mode Exit fullscreen mode

Quantifiers (How Many)

*        Zero or more
+        One or more
?        Zero or one (optional)
{3}      Exactly 3
{2,5}    Between 2 and 5
{3,}     3 or more
Enter fullscreen mode Exit fullscreen mode

Anchors (Position)

^        Start of string
$        End of string
\b       Word boundary
\B       Not a word boundary
Enter fullscreen mode Exit fullscreen mode

Groups and Alternation

(abc)    Capture group — remember the match
(?:abc)  Non-capturing group — match but don't remember
a|b      Either a OR b
\1       Reference to first capture group
Enter fullscreen mode Exit fullscreen mode

Real-World Examples

1. Email Validation

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

emailRegex.test('alex@example.com');     // true
emailRegex.test('not-an-email');         // false
emailRegex.test('user@sub.domain.co.uk'); // true
Enter fullscreen mode Exit fullscreen mode

2. URL Extraction

const urlRegex = /https?:\/\/(www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}[^\s]*/g;

const text = 'Visit https://example.com or http://test.org/path?q=1';
text.match(urlRegex);
// ['https://example.com', 'http://test.org/path?q=1']
Enter fullscreen mode Exit fullscreen mode

3. Phone Number Formatting

// Match US phone numbers in various formats
const phoneRegex = /(\d{3})[-.)]?(\d{3})[-.)]?(\d{4})/;

const phones = [
  '555-123-4567',
  '(555) 123-4567',
  '555.123.4567',
  '5551234567',
];

phones.forEach(phone => {
  const match = phone.match(phoneRegex);
  if (match) {
    const formatted = `(${match[1]}) ${match[2]}-${match[3]}`;
    console.log(`${phone}${formatted}`);
  }
});
// 555-123-4567 → (555) 123-4567
// (555) 123-4567 → (555) 123-4567
// 555.123.4567 → (555) 123-4567
// 5551234567 → (555) 123-4567
Enter fullscreen mode Exit fullscreen mode

4. Password Strength

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

// Requires: lowercase + uppercase + digit + special char + 8+ chars
passwordRegex.test('Password1!');  // true
passwordRegex.test('weak');         // false
passwordRegex.test('NoSpecial1');   // false
Enter fullscreen mode Exit fullscreen mode

5. HTML Tag Extraction

const htmlRegex = /<(\w+)([^>]*)>(.*?)<\/\1>/gs;

const html = '<div class="test">Hello <span>world</span></div>';
const matches = [...html.matchAll(htmlRegex)];

matches.forEach(match => {
  console.log(`Tag: ${match[1]}, Attrs: ${match[2]}, Content: ${match[3]}`);
});
// Tag: div, Attrs:  class="test", Content: Hello <span>world</span>
// Tag: span, Attrs: , Content: world
Enter fullscreen mode Exit fullscreen mode

6. String Cleaning

// Remove HTML tags
'Hello <b>world</b>'.replace(/<[^>]*>/g, '');  // "Hello world"

// Remove extra whitespace
'  too   many   spaces  '.replace(/\s+/g, ' ').trim();  // "too many spaces"

// Convert to title case
'the quick brown fox'.replace(
  /\b\w/g, 
  char => char.toUpperCase()
);  // "The Quick Brown Fox"

// Remove numbers from string
'Order #12345 confirmed'.replace(/\d+/g, '');  // "Order # confirmed"

// Replace multiple dots with single dot
'file....name...txt'.replace(/\.+/g, '.');  // "file.name.txt"
Enter fullscreen mode Exit fullscreen mode

7. Find and Replace with Groups

// Reformat date from MM/DD/YYYY to YYYY-MM-DD
const dateStr = 'Date: 12/31/2026 and 01/15/2026';
const reformatted = dateStr.replace(
  /(\d{2})\/(\d{2})\/(\d{4})/g,
  '$3-$1-$2'
);
// "Date: 2026-12-31 and 2026-01-15"

// Swap first and last name
const names = 'Smith, John; Doe, Jane';
const swapped = names.replace(
  /(\w+),\s*(\w+)/g,
  '$2 $1'
);
// "John Smith; Jane Doe"
Enter fullscreen mode Exit fullscreen mode

JavaScript Regex Methods

// test() — Does it match? (boolean)
/hello/.test('hello world');  // true

// match() — Find all matches
'abc123abc'.match(/abc/g);  // ['abc', 'abc']

// matchAll() — Find matches with groups
const text = 'Jan 5 and Feb 12';
[...text.matchAll(/(\w+) (\d+)/g)].forEach(m => {
  console.log(`${m[1]}: ${m[2]}`);
});

// replace() — Find and replace
'hello world'.replace(/world/, 'regex');  // "hello regex"

// replaceAll() — Replace ALL occurrences
'aabbcc'.replaceAll(/b/g, 'x');  // "aaxxcc"

// search() — Find index of match
'hello world'.search(/world/);  // 6

// split() — Split string by pattern
'a1b2c3'.split(/\d/);  // ['a', 'b', 'c', '']
Enter fullscreen mode Exit fullscreen mode

Common Patterns Library

const patterns = {
  email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
  url: /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,}$/,
  ipv4: /^(\d{1,3}\.){3}\d{1,3}$/,
  date: /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/,
  hexColor: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
  usPhone: /^(\+1)?[\s-]?\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/,
  username: /^[a-zA-Z0-9_-]{3,20}$/,
  strongPassword: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$/,
  creditCard: /^(\d{4}[-\s]?){3}\d{4}$/,
  slug: /^[a-z0-9]+(?:-[a-z0-9]+)*$/,
};
Enter fullscreen mode Exit fullscreen mode

Pro Tips

// 1. Use 'g' flag for global (all matches)
'aaa'.match(/a/);   // ['a'] — first match only
'aaa'.match(/a/g);  // ['a', 'a', 'a'] — all matches

// 2. Use 'i' flag for case-insensitive
/Hello/.test('hello');   // false
/Hello/i.test('hello');  // true

// 3. Use 's' flag for dotAll (dot matches newlines)
/a.b/.test('a\nb');  // false
/a.b/s.test('a\nb'); // true

// 4. Escape special characters with backslash
// Special chars: . * + ? ^ $ { } [ ] \ | ( )
const safe = 'hello.world'.replace(/\./g, '\\.');  // "hello\\.world"

// 5. Use non-capturing groups (?:) for performance
// Bad: /(?:a|b)(?:c|d)/ — doesn't create capture groups
// Good for complex patterns where you don't need groups
Enter fullscreen mode Exit fullscreen mode

What's the most complex regex you've ever written?

Follow @armorbreak for more developer guides.

Top comments (0)