Regular Expressions Explained: Patterns, Flags, and Practical Examples
Learn how regular expressions work in JavaScript: flags, character classes, anchors, and common patterns for emails, URLs, and phone numbers.
Regex is a pattern-matching language embedded in almost every programming environment. The syntax looks intimidating at first — all those backslashes and brackets — but once you recognize the handful of constructs that appear in 90% of real-world patterns, it gets much less mysterious.
When regex is worth it
Regex makes sense when the thing you’re looking for has internal structure: an email address, a version number, a date in a specific format, a line in a log file that starts with a timestamp.
For simple substring matching, use includes(). For “does this string look like a valid phone number,” use regex. The overhead of writing a pattern pays off when plain string methods would need five lines of logic anyway.
The four flags worth knowing
g — global. Without it, the engine finds the first match and stops. Add it and you get all of them.
i — case-insensitive. /error/i catches Error, ERROR, and error.
m — multiline. Normally ^ and $ match the very start and end of the whole string. With m, they match the start and end of each line. This trips up a lot of people.
s — dotAll. The dot . skips newlines by default. With s, it matches them too — useful when your content spans multiple lines.
Combine them as needed: gi, gim, gis.
Patterns that come up constantly
Here’s a handful worth bookmarking:
Email (good enough for most uses)
[\w.+-]+@[\w-]+\.[a-z]{2,}
All integers in a string
\d+
Words starting with a capital letter
\b[A-Z][a-z]+\b
ISO date (YYYY-MM-DD)
\d{4}-\d{2}-\d{2}
URL
https?://[\w./%-?=&#]+
None of these are perfect. The email pattern doesn’t handle every edge case — but something that’s 99% accurate and readable beats a 200-character RFC-compliant monster you’ll never debug when it fails.
Three mistakes that bite everyone
Forgetting to escape literal special characters. The dot . in regex means “any character.” /3.14/ also matches 3x14. If you mean a real dot, write \..
Using ^ and $ on multiline text without the m flag. You end up matching nothing and wondering why.
Nested quantifiers with alternation. (a|ab)+ on a long string that doesn’t match can trigger catastrophic backtracking and lock up the thread. If your pattern has nested groups with quantifiers, test it on a longer input before shipping.
Named capture groups
JavaScript has had named groups since ES2018. The syntax is (?<name>pattern):
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Run that against "2026-05-27" and you get match.groups.year === "2026" instead of having to remember which index is which. Much easier to read six months later.
Using the tester
Paste your pattern into the Regex Tester — just the pattern itself, without the surrounding slashes. Add any flags in the field after the second slash. Drop your test text into the textarea.
Matches highlight immediately. The details section shows each match’s value and position in the string. Named group values appear next to each match too.
Everything runs in the browser — your test data never leaves the page.