In Regexes§
See primary documentation in context for Lookahead assertions
To check that a pattern appears before another pattern, use a lookahead assertion via the before
assertion. This has the form:
<?before pattern>
Thus, to search for the string foo
which is immediately followed by the string bar
, use the following regexp:
/ foo <?before bar> /
For example:
say "foobar" ~~ / foo <?before bar> /; # OUTPUT: «foo»
However, if you want to search for a pattern which is not immediately followed by some pattern, then you need to use a negative lookahead assertion, this has the form:
<!before pattern>
In the following example, all occurrences of foo
which is not before bar
would match with
say "foobaz" ~~ / foo <!before bar> /; # OUTPUT: «foo»
Lookahead assertions can be used also with other patterns, like characters ranges, interpolated variables subscripts and so on. In such cases it does suffice to use a ?
, or a !
for the negate form. For instance, the following lines all produce the very same result:
say 'abcdefg' ~~ rx{ abc <?before def> }; # OUTPUT: «「abc」» say 'abcdefg' ~~ rx{ abc <?[ d..f ]> }; # OUTPUT: «「abc」» my @ending_letters = <d e f>; say 'abcdefg' ~~ rx{ abc <?@ending_letters> }; # OUTPUT: «「abc」»
Metacharacters can also be used in lookahead or -behind assertions.
say "First. Second" ~~ m:g/ <?after ^^ | "." \s+> <:Lu>\S+ / # OUTPUT: «(「First.」 「Second」)»
A practical use of lookahead assertions is in substitutions, where you only want to substitute regex matches that are in a certain context. For example, you might want to substitute only numbers that are followed by a unit (like kg), but not other numbers:
my @units = <kg m km mm s h>; $_ = "Please buy 2 packs of sugar, 1 kg each"; s:g[\d+ <?before \s* @units>] = 5 * $/; say $_; # OUTPUT: «Please buy 2 packs of sugar, 5 kg each»
Since the lookahead is not part of the match object, the unit is not substituted.