/^/

Lesson 14 of 28

Lookbehind

Match a pattern only when it is preceded by something specific, without including that something in the match, using positive lookbehind.

6 min read

Every lookaround you’ve seen so far — lookahead — checks what comes after the current position. Lookbehind does the mirror-image job: it checks what comes before the current position, without including that text in the match. The syntax is (?<=...).

Like lookahead, lookbehind is a zero-width assertion. It doesn’t consume any characters itself — it just asks the engine “does the text immediately before this point match this pattern?” and either allows or blocks the match from continuing.

Matching a value only when preceded by something

A classic use case: extracting a number that follows a currency symbol, without including the symbol itself in the result.

const text = "Price: $42.50";
const match = text.match(/(?<=\$)\d+(\.\d{2})?/);
console.log(match[0]); // "42.50" — the $ is checked, not captured

Without lookbehind, you’d typically capture the $ in a group and then discard it manually. With (?<=\$), the dollar sign is simply never part of the match.

Price: $42.50, Discount: 10%, Total: $38.25 Refund: $5
3 matches· capture groups: 1

Notice that 10% is untouched — those digits aren’t preceded by $, so the lookbehind assertion fails and the engine moves on.

The four lookaround forms

Lookbehind completes the set of lookaround assertions. You now know all four:

Syntax Name Asserts
(?=...) Lookahead What follows is present (not consumed)
(?!...) Negative lookahead What follows is not present
(?<=...) Lookbehind What precedes is present (not consumed)
(?<!...) Negative lookbehind What precedes is not present (next lesson)

Tip

Historically, many regex engines (older versions of Perl-compatible engines, for example) required the pattern inside (?<=...) to have a fixed or bounded length — no unbounded * or + allowed. JavaScript’s engine is more permissive: it supports variable-length lookbehind, so patterns like (?<=\d+\s) are valid. Still, keep lookbehind patterns reasonably simple — deeply nested variable-length lookbehind can be slow to evaluate.

Reading lookbehind left to right

It helps to read (?<=X)Y as “match Y, but only at a position where X sits immediately to the left.” The assertion is checked first conceptually, but nothing about X ends up in match[0] — only Y does.

/(?<=@)\w+/.test("contact: @alice"); // true, matches "alice"

Match names after a title

Given the text "Dr. Smith and Mr. Jones met Dr. Lee", write a pattern using lookbehind that matches a name only when it follows "Dr. " (with the period and space), but not when it follows "Mr. ".

Show solution
/(?<=Dr\. )\w+/g

This matches "Smith" and "Lee", but skips "Jones" because it’s preceded by "Mr. ", not "Dr. ". Notice the period inside the lookbehind is escaped as \. — inside (?<=...), a literal period still needs escaping just like anywhere else in a pattern.

What’s next

Lookbehind has a negative counterpart too. In the next lesson, you’ll learn negative lookbehind ((?<!...)) — matching something only when it is not preceded by a given pattern.

Quick check

What does the pattern (?<=USD )\d+ match in the text "USD 100"?

Which statement best describes how JavaScript handles lookbehind compared to many historically limited regex engines?