W3docs

JavaScript Regex

Learn JavaScript regular expressions (regex): how to create patterns, the flags that change matching, and the core methods for searching and validating text.

Introduction to Regular Expressions (Regex) in JavaScript

Regular expressions, commonly known as regex, are sequences of characters that form search patterns. They are essential tools in programming for text processing tasks like searching, editing, and manipulating string data. Regex is used in various fields such as data validation, parsing, syntax highlighting, and more.

For example, you can quickly check whether a string looks like an email address:

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailRegex.test("[email protected]")); // true
console.log(emailRegex.test("not-an-email"));    // false

Note: This is a simplified pattern. For production validation, consider stricter rules or dedicated libraries.

Where regex is used:

  • Web development: validating form inputs, parsing URLs, and searching within content.
  • Data analysis: extracting specific patterns from large datasets.
  • Text editing: finding and replacing text in documents or codebases.
  • Programming languages: most modern languages, including JavaScript, support regex.

Creating a regular expression

JavaScript gives you two ways to create a regex, and the difference matters in practice.

// 1. Literal syntax — compiled once when the script loads.
const re1 = /\d+/g;

// 2. Constructor — useful when the pattern is built from a variable.
const word = "cat";
const re2 = new RegExp(word + "s?", "i"); // matches "cat" or "cats", case-insensitive

console.log(re1 instanceof RegExp); // true
console.log(re2.source, re2.flags); // cats? i

Use the literal form for fixed patterns — it is shorter and the engine compiles it ahead of time. Reach for the RegExp constructor when the pattern is dynamic (for example, built from user input). Remember that in a string you must double the backslash: "\\d" in a constructor equals \d in a literal.

How regex connects to strings: the core methods

A pattern is only useful together with a method that runs it. These are the ones you will use every day.

const text = "The year 2023 follows 2022.";

// test() → boolean: "does it match anywhere?"
console.log(/\d{4}/.test(text)); // true

// String.match() with /g → array of all matches
console.log(text.match(/\d{4}/g)); // [ '2023', '2022' ]

// String.replace() → returns a new string
console.log(text.replace(/\d{4}/g, "YEAR")); // The year YEAR follows YEAR.

// RegExp.exec() → one match at a time, with capture groups
console.log(/(\d{4})/.exec(text)[1]); // 2023

// String.matchAll() → iterator of full match objects (needs /g)
for (const m of text.matchAll(/(\d{4})/g)) {
  console.log(m[0], "at index", m.index);
}
// 2023 at index 9
// 2022 at index 22

Pick the method by intent: test() for a yes/no check, match()/matchAll() to extract data, and replace() to rewrite text. The g (global) flag is what turns "the first match" into "every match", so it is essential for match, matchAll, and replace-all operations.

Reading a pattern: common building blocks

Most patterns are assembled from a small vocabulary. Here is a working example that uses several pieces at once:

const log = "2023-06-19 ERROR user=42 path=/login";

// \d  digit      \w  word char     \s  whitespace
// .   any char   +   1 or more     [] a set of chars
const match = log.match(/(\d{4}-\d{2}-\d{2})\s+(\w+)\s+user=(\d+)/);

console.log(match[1]); // 2023-06-19  (the date group)
console.log(match[2]); // ERROR       (the level group)
console.log(match[3]); // 42          (the user id group)

Each (...) is a capturing group whose text appears in the result array. \d, \w, and \s are character classes; the quantifiers + and {4} say how many times to repeat the preceding token. Combine these and you can pull structured data out of plain text.

Quick Reference: Flags & Quantifiers

CategorySymbol/FlagDescription
FlagsiCase-insensitive matching
gGlobal match (find all matches)
mMultiline mode (^ and $ match line boundaries)
sDotall mode (. matches newlines). Requires ES2018+ support.
uUnicode mode
ySticky mode (matches only from lastIndex)
Quantifiers*0 or more times
+1 or more times
?0 or 1 time
{n}Exactly n times
{n,}n or more times
{n,m}Between n and m times

Common gotchas

A few surprises trip up almost everyone learning regex in JavaScript:

  • A /g regex remembers where it stopped. When you reuse the same RegExp object with test() or exec(), it advances lastIndex between calls, so the second test() can return false on a string that clearly matches. Use a fresh literal each time, or reset re.lastIndex = 0.

    const re = /a/g;
    const s = "a";
    console.log(re.test(s)); // true
    console.log(re.test(s)); // false — lastIndex moved past the end
  • Dynamic patterns must escape user input. If you build a regex from text the user typed, characters like . or ( are treated as special. Escape them first:

    const escape = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    const userInput = "a.b";
    const re = new RegExp(escape(userInput));
    console.log(re.test("axb"));  // false — the dot is now literal
    console.log(re.test("a.b"));  // true
  • Greedy by default. .+ grabs as much as it can; add ? to make it lazy (.+?). See Greedy and lazy quantifiers.

Learning roadmap

This page is the gateway to the regex part of the course. Work through the following chapters in order for a complete, hands-on understanding:

  1. Patterns and flags — constructing patterns and how the flags (i, g, m, s, u, y) change matching.
  2. Character classes\d, \w, \s and their negations.
  3. Unicode: flag u and class \p{...} — handling multilingual text and emoji.
  4. Anchors: string start ^ and end $ — matching at boundaries.
  5. Multiline mode of anchors, flag m — making ^ and $ match each line.
  6. Word boundary \b — matching whole words.
  7. Escaping special characters — using ., (, ? literally.
  8. Sets and ranges [...] — custom character sets.
  9. Quantifiers +, *, ?, {n} — specifying repetition.
  10. Greedy and lazy quantifiers — controlling how much is matched.
  11. Capturing groups — extracting and naming parts of a match.
  12. Backreferences \n and \k<name> — reusing captured text.
  13. Alternation (OR) | — matching one of several options.
  14. Lookahead and lookbehind — zero-width assertions.
  15. Catastrophic backtracking — diagnosing and avoiding pathological performance.
  16. Sticky flag y, searching at position — anchored, position-based matching.

For the methods that run these patterns, see the RegExp object and its methods and the JavaScript strings chapter.

By the end of these lessons, you will be able to craft effective regex patterns for searching, validating, and transforming text in JavaScript.

Practice
In JavaScript regex, which flag makes a pattern find every match in a string instead of just the first?
In JavaScript regex, which flag makes a pattern find every match in a string instead of just the first?
Was this page helpful?