本页面有中文版。
Cette page est disponible en français.
Esta página está disponible en español.

Lookarounds

Peek without consuming — lookahead and lookbehind are zero-width assertions that check what comes before or after a spot, then step back and let the real match continue.

Read the rules: Lookahead & lookbehind in the Guide →Drill it: Regex wizardry →

What you'll learn

Lookahead Negative lookahead Lookbehind Negative lookbehind Password rules

Steps · 12

  1. 01Peeking without consumingBriefing
  2. 02Positive lookaheadHunt
  3. 03Lookahead for a characterHunt
  4. 04Negative lookaheadHunt
  5. 05"Not followed by"Hunt
  6. 06Positive lookbehindHunt
  7. 07Negative lookbehindHunt
  8. 08Combining assertionsHunt
  9. 09A stricter passwordHunt
  10. 10A word NOT ending in sHunt
  11. 11Golf: q not followed by uHunt
  12. 12Assertions, masteredBriefing

Lookahead and lookbehind in regex

Lookarounds let a regular expression check the text next to a position without making it part of the match. They are zero-width, like anchors: the check passes or fails, and the cursor stays where it was. The rest of the pattern then carries on from that same spot, as if the peek never happened.

A lookahead looks to the right. (?=...) requires that the text ahead matches, and (?!...) requires that it does not. A lookbehind looks to the left: (?<=...) requires the text before to match, and (?<!...) requires that it does not. JavaScript supports all four, and its lookbehind can be any length.

Use them when the context decides the match but should not be part of it: a number only when a unit follows, a word only when a certain prefix is missing, or several rules on one input, such as a password that needs a digit and a capital letter in any order. In a hunt, a lookaround often spares the innocents that share every letter with the targets.

Examples

  1. /\d+(?=px)/

    Catches

    • 12px
    • 300px
    • w: 8px

    Spares

    • 12em
    • px12
    • 12 px

    The lookahead demands px right after the digits, yet the match itself is only the number.

  2. /(?<=#)\w+/

    Catches

    • #tag
    • go #team
    • #2026

    Spares

    • tag
    • # team
    • a#

    The lookbehind checks for # to the left and leaves it out, so the match is the bare tag.

  3. /^(?!.*\d)\w+$/

    Catches

    • hello
    • snake_case

    Spares

    • r2d2
    • top10

    The negative lookahead scans the whole word first with .*, so a digit anywhere in it is enough to reject it.

  4. /(?<!re)play/

    Catches

    • play
    • display
    • player

    Spares

    • replay
    • replays

    The negative lookbehind spares play only when re sits directly before it.

Common mistakes

  • Forgetting `. * in a start-of-text lookahead. ^(?=\d) checks only the first character; write ^(?=.*\d)` to mean a digit appears anywhere.
  • Expecting the peeked text in the result. A lookaround never adds characters to the match, so a replace on \d+(?=px) swaps the number and keeps the px.
  • Copying a JavaScript lookbehind into another flavour. Python's re module needs a fixed length inside (?<=...), and many other flavours limit it, so (?<=\$\d*) works in JavaScript but fails there.

Read the rules: Lookahead & lookbehind in the Guide →Drill it: Regex wizardry →

Read more: Regex lookahead and lookbehind, explained with live boards →

Read more: Password rules with regex lookaheads (and when not to) →