Home >Blog

Regex Lookahead vs Lookbehind: Examples and Tutorial

Published Updated

The one-line difference

Lookahead checks what comes after the current position. Lookbehind checks what comes before it. Both are zero-width: they match a condition without consuming characters, so the rest of the pattern keeps working from the same spot.

Four constructs cover almost every use:

(?=...)   positive lookahead  - matches if ... follows
(?!...)   negative lookahead  - matches if ... does NOT follow
(?<=...)  positive lookbehind - matches if ... precedes
(?<!...)  negative lookbehind - matches if ... does NOT precede

Read them left to right: the ? opens a group, the = or ! sets the direction, and the extra < in lookbehind points the check backwards. That < is the whole visual difference between the two families.

When should you reach for one instead of the other? Think about what your eye does on the page. If you look at a price and want "the number that has a $ in front", that is lookbehind. If you scan a log and want "the word that is followed by a colon", that is lookahead. The syntax follows the direction your brain already points.

What zero-width actually means

Most regex tokens consume the text they match. A lookaround does not. The engine peeks at the surrounding text, confirms the condition, and continues the match from the original position.

\d+(?=px)

This matches digits only when "px" follows them. It does not include "px" in the match:

Input:  12px 34em 56px
Matches: 12    34    56
(34 is skipped because "em", not "px", follows)

Swap in lookbehind and the check moves to the other side:

(?<=\$)\d+

This matches digits only when a dollar sign precedes them:

Input:  $5  €10  $20
Matches: 5        20
(10 is skipped because "€", not "$", precedes)

Because the lookaround is zero-width, the digits are the whole match. That is the behavior people usually want when they say "match the number, not the currency symbol." It also means you can stack lookarounds on the same position — (?<=\$)(?=\d{2}) requires both a dollar sign before and two digits after, and still matches nothing but what the middle pattern produces.

Positive lookahead (?=...)

The workhorse of lookarounds. Use it to require something after the match without including it. A classic is matching a word only when it is the last word of a sentence:

\w+(?=\.)
Input:  "End the sentence. Then continue."
Matches: sentence

Or requiring a minimum length while keeping the matched text clean:

(?=.*\d)[a-z]+

This only matches lowercase runs in strings that contain at least one digit somewhere. The lookahead scans ahead, finds the digit, and lets the [a-z]+ proceed. Password validators use this shape constantly: several lookaheads, each enforcing one rule, none of them consuming the password itself.

Negative lookahead (?!...)

Use it to exclude a continuation. Matching "foo" not followed by "bar":

foo(?!bar)
Input:  foobar foobaz
Matches:        foo  (second one only)

This pattern is everywhere in validation: "an address that does not end with .example", "a username that is not followed by a banned suffix." The negative lookahead is the cheapest way to say "anything but this." One caution: it checks a single position, so foo(?!bar) will still match the "foo" inside "foobar" if you test against a substring where the engine starts at the "foo" — run it against the full string and check the boundaries you actually mean.

Positive lookbehind (?<=...)

Requires a prefix without consuming it. Extracting numbers after a fixed label:

(?<=price: )\d+
Input:  price: 99  cost: 40  price: 12
Matches:       99              12

Lookbehind is pickier than lookahead in most engines: the pattern inside must have a fixed length. (?<=\d{3}) is fine; (?<=\d+) is rejected in JavaScript and Python because the length is unknown.

Negative lookbehind (?<!...)

Matches only when a prefix is absent. The classic is "match a number not preceded by a minus sign":

(?<!-)\d+
Input:  5 -3 7 -8 9
Matches: 5    7    9

Same fixed-length rule applies. If you need a variable-length negative lookbehind, you usually restructure the pattern or fall back to a capture group and a check in code.

Lookahead vs lookbehind side by side

The same task solved twice, once in each direction, shows why the choice matters. Extracting the key from "key=value":

\w+(?==)      # lookahead: key when "=" follows
(?<=\w+=)\w+  # lookbehind: value when "key=" precedes
Input:  user=alice role=admin
Lookahead:  user     role
Lookbehind:      alice     admin

Neither is "better" — they answer different questions. Lookahead is for conditions on what follows, lookbehind for conditions on what precedes. Use the one that matches the sentence you would say out loud about the data.

Match position with lookahead checking forward and lookbehind checking backward

One more practical difference: lookahead is free to roam. Because the engine already has the rest of the string in front of it, variable-length lookahead like (?=\w{2,}) is no trouble anywhere. Lookbehind has to rewind, which is exactly why engines impose the fixed-length rule on it. If a tool you are using rejects your lookbehind, that restriction, not your syntax, is usually the culprit.

Engine support and the fixed-length rule

Lookahead works everywhere, including JavaScript, Python, PHP, Ruby, and PCRE. Lookbehind is younger. JavaScript added it in ES2018, Python has supported fixed-length lookbehind since 3.5, and PCRE allows some variable-length forms. Go's regexp package has no lookaround at all, and neither does RE2 — if you are deploying to Go, plan around capture groups instead.

Three rules of thumb before you commit to a pattern:

  • Test it in the target engine. A pattern that works in a PCRE tester can fail in Python or JavaScript for the same input.
  • Keep lookbehind fixed-length. If the engine complains, the fix is usually a capture group plus a conditional check in code.
  • Prefer capture groups for extraction. When you control the code, (key)=(\w+) with groups 1 and 2 is simpler to read than two lookarounds.

Paste both variants into a regex lookahead explained guide or a live tester like this site's regex tester and watch the match positions change as you flip between the two directions.

FAQ

What is the difference between lookahead and lookbehind?
Lookahead checks text after the current position, lookbehind checks text before it. Both are zero-width, so neither consumes characters.

What does (?=...) mean in regex?
Positive lookahead: the match continues only if the pattern inside appears immediately after the current position.

What does (?<=...) mean in regex?
Positive lookbehind: the match is valid only if the pattern inside appears immediately before the current position.

Does JavaScript support lookbehind?
Yes, since ES2018. Older environments need a transpiled or rewritten pattern.

Why does my lookbehind pattern fail in Python?
Python's re module requires fixed-length lookbehind. Variable-length alternatives like (?<=\d+) raise an error; use a fixed pattern or a capture group instead.

Are lookarounds slow?
Usually not, but pathological patterns can backtrack heavily. Test against real input at expected scale before using them on hot paths.

Start with the positive forms — (?=...) and (?<=...) — until the syntax is comfortable, then add negatives. Most real patterns need one lookaround at most, and the simpler pattern is the one that survives contact with production data.

FAQ

What is the difference between lookahead and lookbehind?
Lookahead checks text after the current position, lookbehind checks text before it. Both are zero-width, so neither consumes characters.
What does (?=...) mean in regex?
Positive lookahead: the match continues only if the pattern inside appears immediately after the current position.
What does (?
Positive lookbehind: the match is valid only if the pattern inside appears immediately before the current position.
Does JavaScript support lookbehind?
Yes, since ES2018. Older environments need a transpiled or rewritten pattern.
Why does my lookbehind pattern fail in Python?
Python's re module requires fixed-length lookbehind. Variable-length alternatives like (?
Are lookarounds slow?
Usually not, but pathological patterns can backtrack heavily. Test against real input at expected scale before using them on hot paths.

目次

情報

  • ヒット49
  • 公開日2026/10/08
0/500
敬意をもってご意見をお聞かせください。

もっと投稿

このセクションの記事をさらに探索
Regex for IP Addresses: Accurate IPv4 and IPv6 Validation Examples
Sep 09, 2026450ビュー

Regex for IP Addresses: Accurate IPv4 and IPv6 Validation Examples

Use regex to find possible IP addresses, then use the right validation rule for the job. This guide covers loo...

#regex for IP address#IP address regex#IPv4 regex#IPv6 regex
Password Validation Regex: Examples for Length, Numbers, Symbols, and Strong Passwords
Sep 07, 2026447ビュー

Password Validation Regex: Examples for Length, Numbers, Symbols, and Strong Passwords

Learn practical password validation regex patterns for length, digits, symbols, and mixed character classes. T...

#password validation regex#regex for password validation#strong password regex#regex lookahead
How to Validate a URL with Regex: HTTP, HTTPS, Domains, and Query Strings
Sep 03, 2026385ビュー

How to Validate a URL with Regex: HTTP, HTTPS, Domains, and Query Strings

Build a practical HTTP and HTTPS URL regex by separating schemes, DNS domains, ports, paths, query strings, an...

#URL validation regex#regex for URL validation#HTTP URL regex#HTTPS URL regex
How to Extract Email Addresses from Text with Regex in Python and JavaScript
Sep 15, 2026345ビュー

How to Extract Email Addresses from Text with Regex in Python and JavaScript

Extract email addresses from any text with regex in Python and JavaScript: the pattern explained piece by piec...

#regex extract email#email regex python#email regex javascript#extract emails from text
What Regex Should You Use for Phone Numbers? Patterns for US and International Formats
Aug 28, 2026328ビュー

What Regex Should You Use for Phone Numbers? Patterns for US and International Formats

Compare practical regex patterns for US formatted numbers, normalized local numbers, plus-prefixed internation...

#phone number regex#regex for phone number#US phone regex#international phone regex
How to Replace Text with Python Regex: re.sub() Examples and Common Mistakes
Sep 18, 2026323ビュー

How to Replace Text with Python Regex: re.sub() Examples and Common Mistakes

Learn how to replace text safely with Python re.sub(), including capture groups, callback functions, case-inse...

#python regex replace#re.sub#regex capture groups#regex callback
フィードバックメール