Interactive Introduction to Regular Expressions in JavaScript
Regular expressions are patterns that describe text. They look cryptic at first, but once you understand the building blocks, they become surprisingly intuitive. In this post, I'm going to walk through how regex works, step by step, with interactive examples you can play with along the way.
By the end, you'll be able to match patterns, validate input, and transform text. Let's start with something simple.
Matching text
At its core, a regular expression just asks one question: "Does this pattern exist in my text?"
The pattern /hello/ matches the exact sequence of characters h-e-l-l-o. Nothing fancy. It either finds that sequence or it doesn't.
Try changing the pattern below. See which strings match and which don't.
Your first pattern
Change the pattern and watch the results
hello worldmatchsay hellomatchhi thereno matchHELLOno matchhelloooomatchA few things to notice here. First, "HELLO" doesn't match because regex is case-sensitive by default. Second, "helloooo" does match because the pattern only needs to exist somewhere in the string. It doesn't have to match the whole thing.
What if we want to match regardless of case? We add a flag. Try typing i in the flags field below.
Case insensitivity
Add 'i' to the flags field
Hello Worldno matchHELLO!no matchhellomatchhino matchHeLLono matchThe i flag tells the regex engine to ignore case. Flags go after the closing slash and modify how the whole pattern behaves. You'll see more flags later.
Character classes
So far we've only matched exact text. But what if you want to match any digit? Or any letter? That's where character classes come in.
Instead of matching a specific character, character classes match a category of characters. Click through the buttons below to see what each one matches.
Character classes
Click a character class to see what it matches
[0-9]These shortcuts are way cleaner than spelling out every possibility. Writing \d is much nicer than [0123456789].
You can also create your own character sets using square brackets. The pattern [aeiou] matches any vowel. The pattern [a-z] matches any lowercase letter. The hyphen creates a range.
Custom character sets
Edit the pattern and test string to see matches
Want to match everything except certain characters? Put a ^ inside the brackets. The pattern [^0-9] matches any character that is not a digit.
Quantifiers
Here's where regex starts to get powerful. What if you want to match multiple digits in a row?
You could write \d\d\d to match exactly three digits. But that's clunky. What if you don't know how many digits there will be?
Quantifiers let you specify how many times a pattern should repeat. Play with the buttons below to see each one in action.
Quantifiers
See how quantifiers control repetition
/go+l/Here's what each quantifier means:
| Quantifier | Meaning |
|---|---|
+ | One or more |
* | Zero or more |
? | Zero or one (optional) |
{n} | Exactly n times |
{n,m} | Between n and m times |
The difference between + and * is subtle but important. The plus sign requires at least one match. The asterisk allows zero matches, which means it can match "nothing" and still succeed.
A practical example
Let's put this together with a real example. Say you want to validate phone numbers in the format XXX-XXX-XXXX.
Your first attempt might look like this:
/\d\d\d-\d\d\d-\d\d\d\d/
It works, but all those \ds make it hard to see what's going on. We can use quantifiers to clean it up:
/\d{3}-\d{3}-\d{4}/
Much better. But what about phone numbers without hyphens? We can make the hyphens optional using ?:
/\d{3}-?\d{3}-?\d{4}/
Watch how each pattern handles different phone number formats:
Building a phone pattern
Watch how different patterns validate phone numbers
/\d\d\d-\d\d\d-\d\d\d\d/202-588-6500✓ Valid67-500-647✗ Invalid2025886500✗ Invalid123-456-7890✓ Valid12-34-5678✗ Invalidabc-def-ghij✗ InvalidClick through the different patterns. Notice how the "With +" version is too loose. It matches 67-500-647 because \d+ allows any number of digits, not just three.
Boundaries
Sometimes you want to match a pattern only in certain positions. Maybe you want to find the word "cat" but not match "catalog" or "scattered".
Boundary markers let you do exactly that.
Boundaries
See how ^ $ and \\b control where patterns match
/cat/gHere are the key markers:
| Marker | Meaning |
|---|---|
^ | Start of string |
$ | End of string |
\b | Word boundary |
The word boundary \b is especially useful. It matches the position between a word character and a non-word character. It doesn't match any actual character. It matches a position.
So /\bcat\b/ means: match "cat" only when it appears as a complete word.
Groups
Parentheses group parts of a pattern together. This is useful when you want to apply a quantifier to multiple characters at once.
/(ho)+/ // matches "ho", "hoho", "hohoho", etc.
The pipe | lets you match alternatives:
/cat|dog/ // matches "cat" or "dog"
You can combine these:
/watch(es|ed|er)?/ // matches watch, watches, watched, watcher
Groups with quantifiers
See which strings match the pattern
hamatchhahamatchhahahamatchhno matchahamatchhahmatchFind and replace
Regex really shines when you're transforming text. JavaScript's replace() method can take a regex pattern as its first argument.
Basic replacement
See how regex replace works
g flag for global replace, or use $1, $2 to reference capture groupsWithout the g flag, only the first match gets replaced. Add g to replace all matches.
Here's where it gets really useful. You can reference captured groups in the replacement string using $1, $2, and so on.
Swapping words
See how regex replace works
g flag for global replace, or use $1, $2 to reference capture groupsThe pattern (\w+) (\w+) captures two words. In the replacement, $1 is the first captured word and $2 is the second. So "hello world" becomes "world hello".
Quick reference
Here's everything we covered:
Character classes
\dmatches any digit\wmatches any word character\smatches any whitespace.matches any character except newline[abc]matches a, b, or c[^abc]matches anything except a, b, or c[a-z]matches any character from a to z
Quantifiers
+means one or more*means zero or more?means zero or one{n}means exactly n times{n,m}means n to m times
Anchors
^matches start of string$matches end of string\bmatches word boundary
Groups
(abc)creates a capture groupa|bmatches a or b
Flags
ifor case insensitivegfor global (match all)
Playground
The best way to learn regex is to experiment. Here's a sandbox to try things out.
Experiment
Edit the pattern and test string to see matches
Try these challenges:
- Match all words that start with a vowel
- Match words that are exactly 5 letters long
- Match "the" only when it starts with a capital T
Regex takes practice. The syntax is dense, but once it clicks, you'll find yourself reaching for it all the time.
