regexhelper
Test a pattern. Copy a ready-made one. No signup.

Lookahead and Lookbehind in Regex

Lookarounds let you assert that something does — or does not — appear before or after your match, without including it in the result. Here is each of the four forms with an example you can test.

A lookaround is a zero-width assertion: it checks a condition but consumes no characters, so the matched text does not include it.

The four forms

SyntaxNameAsserts
(?=X)Positive lookaheadWhat follows is X
(?!X)Negative lookaheadWhat follows is not X
(?<=X)Positive lookbehindWhat precedes is X
(?<!X)Negative lookbehindWhat precedes is not X

Positive lookahead — price without the currency symbol

\d+(?=\s*USD)

Matches 42 in 42 USD but not the USD. The number is captured; the currency is only asserted.

Negative lookahead — a word not followed by another

foo(?!bar)

Matches foo in foobaz but not in foobar.

Positive lookbehind — amount after a symbol

(?<=\$)\d+(\.\d{2})?

Matches 19.99 in $19.99 without including the dollar sign.

Negative lookbehind — a number not preceded by a minus

(?<!-)\b\d+\b

Matches positive numbers but skips -5.

A classic combo: password rules

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$

Stacked lookaheads each check for one requirement (a lowercase letter, an uppercase letter, a digit) before .{8,} checks the length. This is how most "strong password" patterns work.

Engine support

Lookahead works everywhere. Lookbehind is supported in modern JavaScript (V8/Node, all current browsers), PCRE, Python, .NET, Java and Go's regexp2, but older or POSIX engines may reject it. Variable-length lookbehind is allowed in .NET and modern JS but not in classic PCRE.

FAQ

Does a lookahead consume characters?

No. It is zero-width — after a lookahead succeeds, the engine's position does not move, so the asserted text is not part of the match and can be matched again by later tokens.

Can I use variable-length lookbehind?

It depends on the engine. .NET and modern JavaScript allow it. Classic PCRE (and therefore many PHP setups) require fixed-length lookbehind, so (?<=abc) is fine but (?<=a+) is not.

Why use a lookahead instead of a capturing group?

When you want to require context but exclude it from the match — for example to grab a number that is followed by a unit without capturing the unit itself.