DevAcademy
LearnJavaScriptRegular Expressions
AdvancedJavaScript

Regular Expressions

Learn how to build and use regular expressions in JavaScript — patterns, flags, capture groups — and how to apply them with test(), exec(), match(), replace(), and split().

Reading Time

20 min

Lesson

Lesson 43 of 48

What is a Regular Expression?

A regular expression (regex) is a pattern used to match, search, and manipulate text. Instead of manually checking characters one by one, you describe a pattern once — "a digit followed by three letters," for example — and let the regex engine find every place that pattern occurs. Regexes are indispensable for validating input, extracting pieces of a string, and doing search-and-replace far more powerful than a plain string match.

Creating a Regular Expression

There are two ways to create a regex: the literal syntax, /pattern/flags, and the RegExp constructor, new RegExp('pattern', 'flags'). The literal form is more common and slightly faster since it's compiled when the script loads, but the constructor form is necessary when you need to build a pattern dynamically from a string, such as one built from user input.

Two Ways to Create a Regex

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Flags

Flags change how a regex behaves and go after the closing slash. The three you'll use most: g (global) finds all matches instead of stopping at the first one, i (case-insensitive) ignores letter casing, and m (multiline) makes ^ and $ match the start/end of each line rather than only the start/end of the whole string.

Common Flags

FlagNameEffect
gglobalFind all matches, not just the first
icase-insensitiveIgnore uppercase/lowercase differences
mmultiline^ and $ match the start/end of each line

Character Classes and Quantifiers

Character classes match categories of characters: \d matches any digit, \w matches any word character (letters, digits, underscore), and \s matches any whitespace character. Quantifiers control how many times something can repeat: * means zero or more, + means one or more, ? means zero or one, and {n,m} means between n and m times. Anchors ^ and $ pin a match to the start or end of the string.

Character Classes and Quantifiers Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

test() and exec() on RegExp

test() returns a simple boolean — did the pattern match anywhere in the string? exec() goes further: it returns an array with details about the match (the matched text, capture groups, and the index it was found at), or null if there was no match. With the g flag, calling exec() repeatedly on the same regex advances through successive matches each time.

test() vs. exec()

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

String Methods That Take a Regex

Strings have several methods that accept a regex: match() returns matches (all of them, as an array of strings, when the g flag is used), matchAll() returns an iterator of full match objects including capture groups, replace() swaps the first match (or all matches with the g flag) for a replacement, replaceAll() requires the g flag and replaces every match, and split() divides a string wherever the pattern matches.

match(), replace(), and split()

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Capture Groups

Parentheses inside a pattern create a capture group — a piece of the match you can pull out separately. Groups are numbered by their order of opening parenthesis, accessible on the result of exec() or match() by index. Named groups, written as (?<name>...), let you refer to a captured piece by name instead of a numeric index, which makes patterns with several groups much easier to read.

Capture Groups, Including Named Groups

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Practical Example: Loose Email Validation

Fully validating an email address with a regex is notoriously hard (and arguably not worth doing precisely), but a loose check is a common real-world need — enough to catch obvious typos before sending a request to the server.

A Loose Email Check

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Quick Reference

  • \d — a digit, \w — a word character, \s — whitespace
  • * — zero or more, + — one or more, ? — zero or one, {n,m} — between n and m
  • ^ — start of string (or line, with m), $ — end of string (or line, with m)
  • test() → boolean, exec() → match details or null
  • match()/matchAll()/replace()/replaceAll()/split() — string methods that accept a regex

Use Named Groups for Readability

When a pattern has more than one or two capture groups, named groups (?<name>...) make the code that reads them far easier to follow than tracking numeric indices like match[1], match[2], and match[3].

Don't Forget the g Flag

Forgetting the g flag is a common source of bugs: match() without it returns only the first match (with extra details) instead of an array of all matches, and replace() without it only replaces the first occurrence. replaceAll() will throw a TypeError if you pass it a regex without the g flag.

Interview Questions

Quick Quiz

1. Which flag makes a regex find all matches instead of stopping at the first one?

2. What does \d match?

3. What does test() return?

4. How do you access a named capture group called "year" from a match result?

5. What happens if you call replaceAll() with a regex that lacks the g flag?