Once you're comfortable with basic regex, you'll eventually run into a need like this: match something, but only when it's preceded or followed by something specific — and that surrounding context shouldn't appear in the match result.
That's exactly what lookahead and lookbehind are for.
One Thing to Understand First: Lookarounds Don't Consume Characters
With normal regex matching, every character the engine matches advances its position by one. Match ab and the engine moves past a, then past b.
Lookarounds are different. They look forward or backward to check whether a pattern is present, but they don't advance the position, don't consume characters, and don't include their content in the match result.
That's the single most important thing to understand about lookarounds.
The Four Types
| Type | Syntax | Meaning |
|---|---|---|
| Positive lookahead | X(?=Y) |
Match X, but only when followed by Y |
| Negative lookahead | X(?!Y) |
Match X, but only when not followed by Y |
| Positive lookbehind | (?<=Y)X |
Match X, but only when preceded by Y |
| Negative lookbehind | (?<!Y)X |
Match X, but only when not preceded by Y |
Memory trick: = means exists, ! means does not exist. (?= looks right, (?<= looks left.
Positive Lookahead: (?=...)
Extract numbers from 30€ without capturing the euro sign.
const str = "apples $5, oranges 30€, bananas 15kr";
str.match(/\d+(?=€)/g);
// ["30"]
// € is not in the result — (?=€) only asserts, doesn't consume
Negative Lookahead: (?!...)
Match http but not https.
const str = "visit http://example.com or https://secure.com";
str.match(/http(?!s)/g);
// ["http"] only the first one matched
Positive Lookbehind: (?<=...)
Extract only numbers that follow a dollar sign.
const str = "Item A: $30, quantity: 5, Item B: $120";
str.match(/(?<=\$)\d+/g);
// ["30", "120"] — the standalone 5 is not matched
Extract a CSS color value after the colon.
const css = "--primary-color: #3498db;";
css.match(/(?<=:\s*)#[0-9a-f]+/i);
// ["#3498db"]
Negative Lookbehind: (?<!...)
Match unescaped quotes — not preceded by a backslash.
const str = String.raw`he said \"hello\" and "world"`;
str.match(/(?<!\\)"/g);
// only matches the quotes around "world"
Filter out .min.js files.
const files = ["app.js", "app.min.js", "utils.js"];
files.filter(f => /(?<!\.min)\.js$/.test(f));
// ["app.js", "utils.js"]
Combining Multiple Lookaheads for Password Validation
Stack several assertions together, each checking a different condition from the same starting position.
const passwordRegex = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/;
passwordRegex.test("weak"); // false
passwordRegex.test("StrongPass1!"); // true
passwordRegex.test("nouppercase1!"); // false — no uppercase
Why (?=.*[A-Z]) instead of just placing [A-Z] in the pattern? Because uppercase can appear anywhere. The .* inside the lookahead scans the whole string to find one, and since the lookahead doesn't consume characters, the next assertion starts from the same position again. Each assertion runs independently from the same point — that's what makes stacking work.
JavaScript Lookbehind Compatibility
Lookbehind was added in ES2018. IE doesn't support it at all; Safari requires 14.1+.
For older browser support, use a capturing group instead:
// Lookbehind (ES2018+)
"price: $30".match(/(?<=\$)\d+/); // ["30"]
// Alternative: capturing group
const match = "price: $30".match(/\$(\d+)/);
const price = match ? match[1] : null; // "30"
Lookahead works in all modern browsers without compatibility concerns.
Python Lookbehind Requires Fixed Width
import re
# Variable-width lookbehind is not supported in Python's re module
re.findall(r'(?<=a+)b', 'aaab')
# error: look-behind requires fixed width pattern
re.findall(r'(?<=a)b', 'aab') # fixed width — OK
re.findall(r'(?<=aa)b', 'aab') # fixed width — OK
JavaScript (ES2018+) supports variable-width lookbehind; Python's built-in re does not. For variable-width lookbehind in Python, use the regex package from PyPI.
The easiest way to debug lookarounds is to visualize them — paste your pattern into the Regex Visualizer and watch assertion ranges and match results render in real time.
Article URL:https://toolshu.com/en/article/regex-lookahead-lookbehind
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License 。



Loading...