Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex assertions working only in lookahead and lookbehind fashion

While trying to come up with some examples for solving this issue, I came up with this snippet:

my regex key {^^ <![#-]> \d+ }
say "333" ~~ &key;                         # OUTPUT: «「333」␤»
say "#333" ~~ &key;

say '333$' ~~ m/ \d+ <?[$]>/;              # OUTPUT: «「333」␤»
say '333' ~~ m/ \d+ <?[$]>/;
say '$333' ~~ m/<?[$]> \d+ /;

only the statements indicated return 「333」, which seems to indicate <! > works as lookahead assertion, while <? > works only as zero-width lookbehind. Is that the case? If that's the case, what's the way of creating a positive look-ahead assertion and a negative look-behind?

like image 671
jjmerelo Avatar asked Jan 27 '23 01:01

jjmerelo


1 Answers

I think you've just misinterpreted your experiments.

<? > works only as zero-width lookbehind. Is that the case?

No. It's a lookahead. Per your own experiments:

say '333$' ~~ m/ \d+ <?[$]>/;              # OUTPUT: «「333」␤»

The \d+ matches 333.

The <? > does a zero width assertion. What does it assert? It asserts, positively (? not !) that the next character (so it's a lookahead, like most regex patterns) must be $. The next character is indeed $, so the assertion succeeds. But as it's a zero-width assertion, it doesn't move the matching cursor forward. (That's what the "zero-width" aspect means.)

Then the overall regex is done, the overall regex succeeds, and the overall regex captures just 333.

say '333' ~~ m/ \d+ <?[$]>/;

In this instance there is no $ for the positive assertion to match, so the overall match fails.

say '$333' ~~ m/<?[$]> \d+ /;

As before, the <?[$]> asserts that the next character is a $. It is, so it succeeds. But, because it's a zero-width assertion, it does not advance the cursor.

The \d+ then fails (because the matching cursor is still pointing at a $).

like image 57
raiph Avatar answered Jan 30 '23 06:01

raiph