Regex lookahead and lookbehind, explained with live boards
Lookarounds let a regex check what comes before or after a spot without matching it. Here's how all four work, where they shine, and when a plain pattern is shorter.

· 7 min read
/q(?!u)/
match
- iraq
- qatar
- qi
spare
- queen
- quiet
- quote
Most of a regex consumes text. cat eats three characters, \d+ eats every digit it can, and the engine moves past whatever it matched.
Lookarounds don't. They stand at one spot in the string, peek forward or backward, and report yes or no. They match zero characters. That one idea lets you say things a plain pattern can't, like "a q that isn't followed by a u" or "a number that comes right after a dollar sign, without the dollar sign".
Every example below is live: edit the pattern and the lines update, or hit Try it to open it in the Playground.
01The four lookarounds
| Syntax | Name | Succeeds when… |
|---|---|---|
(?=X) |
positive lookahead | X comes next |
(?!X) |
negative lookahead | X does not come next |
(?<=X) |
positive lookbehind | X comes right before |
(?<!X) |
negative lookbehind | X does not come right before |
The arrow in the name tells you the direction: lookahead checks the text after the current position, lookbehind checks the text before it. = means "must be there", ! means "must not be there".
02Negative lookahead: a q without a u
In English, q is almost always followed by u. Catching the exceptions is a one-liner with a negative lookahead:
Notice iraq. A tempting alternative is q[^u], "a q followed by anything except u". But [^u] has to match a character, and the q in iraq is the last letter. The lookahead only asks that the next thing isn't a u, and the end of the string isn't a u.
03Positive lookahead: match one part, check the next
A positive lookahead lets you require some context without including it in the match. Here we want the number, but only when it's an amount in dollars:
/\d+(?= dollars)/Should match1/1
- it costs 40 dollars
Should not2/2
- 40 euros
- dollars 40
This matters whenever you replace or extract text. Run a find-and-replace with \d+(?= dollars) and you change the number, while the word "dollars" stays exactly as it was.
04Stacking lookaheads: several rules at once
Because lookaheads don't move the position, you can put several at the same spot. Each one checks a different rule over the whole string. This is the classic password check: at least one digit, at least one uppercase letter, and eight or more characters:
/^(?=.*\d)(?=.*[A-Z]).{8,}$/Should match2/2
- Hunter2024
- Regex1Hunter
Should not3/3
- hunter2024
- SHORT1
- NoDigitsHere
Read it left to right: from the start, somewhere ahead there's a digit; from the same start, somewhere ahead there's a capital; then match 8 or more characters to the end. Order doesn't matter, which is exactly why lookaheads beat writing out every arrangement.
05Lookbehind: check what came before
Lookbehind is the mirror image. (?<=\$)\d+ matches digits that come right after a dollar sign, without the $ itself:
And the negative form finds numbers that are not prices:
That last caption hides a real trap. Without the word boundaries, (?<!\$)\d+ would happily match 00 in $100, because the 0s aren't directly after the $. Lookbehind only checks the spot where the match starts, so you often need \b or an anchor to pin that spot down.
06When lookarounds win at golf, and when they don't
In regex golf, every character counts, so it's worth knowing when a lookaround pays for itself.
For two letters in any order, a plain alternation is shorter: a.*e|e.*a is 9 characters, and (?=.*a).*e is 10. But the number of orderings grows fast (2 for two letters, 6 for three, 24 for four), while each extra lookahead costs a fixed seven characters. Here's a board where every monster contains an a, an e and an i, in any order:
Boardcertain · machine · relation · dialect · patience vs garden · pencil · plastic · money · violin
- every ordersolves it47
/a.*e.*i|a.*i.*e|e.*a.*i|e.*i.*a|i.*a.*e|i.*e.*a/ - lookaheadssolves it17
/(?=.*a)(?=.*e).*i/
The lookahead version works because a regex search tries each position in turn. At the very first position, both lookaheads scan the whole word, so it doesn't matter where the a and e are.
07Your turn
Same idea, new board. Every monster has at least one digit and at least one capital letter, in either order:
Catch the words that have a digit and a capital letter, in any order.
Targets · 0/5 caught
- Hunt3rtarget
- R2d2target
- x9Ytarget
- Agent47target
- 7Seastarget
Innocents · 0 hit
- hunterinnocent
- r2d2innocent
- AGENTinnocent
- 1999innocent
- x9yinnocent
Type a regex — the board updates as you go.
08Things to know before you use them
- Lookarounds are zero-width.
(?=\d)on its own matches an empty string in front of a digit. That's handy for inserting text (like thousands separators) and confusing when you expected to match the digit itself. - Support varies. JavaScript (all modern browsers and Node), Python, Java, .NET and PCRE all support lookahead and lookbehind. Python's built-in
remodule only allows fixed-width lookbehind, so(?<=\$\d*)is an error there, while JavaScript accepts it. Go's standardregexppackage supports no lookarounds at all. - Prefer the plain pattern when it's clear.
q[^u]|q$works too, and some readers find it easier to follow. Use a lookaround when it makes the intent obvious or saves real complexity.
09Keep practising
- The regex guide has a quick reference with more live examples.
- Lookarounds turn up on harder daily boards. Today's hunt might need one.