Regexes & grammars

Lookahead & lookbehind assertions

Full

Match a position based on what follows or precedes, without consuming it.

A lookaround checks the text around a position without including it in the match. <?before …> succeeds when the following text matches; <?after …> looks at what precedes. Each has a negated form (<!before> / <!after>). None consume characters — they constrain a position.

Positive lookahead — <?before> #

say "foobar" ~~ /foo <?before bar>/;
say so "foobaz" ~~ /foo <?before bar>/;
Output
「foo」
False

The match is just foo (the lookahead adds no characters), and it only succeeds when bar follows — so foobaz fails.

Negative lookahead — <!before> #

<!before …> matches only when the following text does not match.

say so "catfish" ~~ /cat <!before fish>/;
say so "catdog" ~~ /cat <!before fish>/;
Output
False
True

cat is rejected in catfish (fish follows) and accepted in catdog.

Lookbehind — <?after> / <!after> #

<?after …> is the mirror image: it constrains what comes before the position, again without consuming it. This is the clean way to match a value only when it follows a fixed prefix — capturing the value alone, not the prefix.

"cost: 42 USD" ~~ / <?after \: \s > (\d+) /;
say ~$0;
Output
42

The digits are captured, but the : that had to precede them is not part of the match. It works inside a substitution too — replace bar only when foo sits in front of it:

say "foobar".subst(/ <?after foo> bar /, "BAZ");
Output
fooBAZ

<!after …> negates it — match only where the given text does not precede.

Notes #