Regex Lookahead and Lookbehind Explained
Lookahead and lookbehind are zero-width assertions — they check what's around a match without consuming characters. The matched text doesn't include the lookahead/lookbehind itself.
Positive lookahead (?=...)
Match foo only when followed by bar:
/foo(?=bar)/
"foobar" → matches "foo"
"foobaz" → no match
"foobarfoo" → matches first "foo"
The bar part is checked but not included in what's captured.
Negative lookahead (?!...)
Match foo only when not followed by bar:
/foo(?!bar)/
"foobar" → no match
"foobaz" → matches "foo"
Useful for excluding a pattern: match a word that isn't a reserved keyword, or a number not followed by px.
Positive lookbehind (?<=...)
Match bar only when preceded by foo:
/(?<=foo)bar/
"foobar" → matches "bar"
"bazbar" → no match
Negative lookbehind (?<!...)
Match bar only when not preceded by foo:
/(?<!foo)bar/
"foobar" → no match
"bazbar" → matches "bar"
Real-world examples
Match a price number without the $ sign:
/(?<=\$)\d+(\.\d{2})?/
Captures 9.99 from $9.99, leaving out the dollar sign.
Match a word not at the end of a sentence:
/\b\w+\b(?![.!?])/g
Strip leading zeros from a number:
"007".replace(/(?<=^)0+/, "") // "7"
Browser and Node.js support
Lookbehind ((?<=...), (?<!...)) was added in ES2018. It works in Chrome, Firefox, Safari 16.4+, and Node.js 10+. If you're targeting older environments, stick to lookahead only.
Quick reference
| Syntax | Name | Matches when... |
|---|---|---|
(?=...) | Positive lookahead | Followed by pattern |
(?!...) | Negative lookahead | NOT followed by pattern |
(?<=...) | Positive lookbehind | Preceded by pattern |
(?<!...) | Negative lookbehind | NOT preceded by pattern |
Test it live
Paste any regex and test string into the regex tester to see matches highlighted in real time — no setup needed. For more patterns to build on, see common regex patterns or the full regex cheat sheet.
Got a config file to check?
Open the config toolkit →