Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does =~ only evaluate once?

Tags:

regex

perl

In this example script:

#perl 5.26.1 
$foo = "batcathat";

if ($foo =~ /cat/g) {
    print "yes\n";
} else {
    print "no\n";
}

if ($foo =~ /cat/g) {
    print "yes\n";
} else {
    print "no\n";
}

This will print:

yes
no

The expected output is:

yes
yes

I can confirm by printing the string that it has not been mutated by running the regex match.

Why does Perl seemingly only evaluate a regex expression once? I could find no information about this on Google or manuals, and the behaviour is not intuitive to me. I expect that each time you evaluate a regex match, it starts from fresh, and does not remember anything about the previous match.

Edit: For future context, this question was asked after I found a bit of code looking like this:

while ( $foo =~ /pattern/g) { $some_incrementing_var++ };

I did not understand initially how this while loop could ever terminate, as on first glance it looked like an infinite loop.

like image 446
Lou Avatar asked Sep 04 '26 14:09

Lou


1 Answers

//g in scalar context starts to match where the previous /g match ended. Since cat only occurs only once, it returns false to indicate there's no match the second time.

This is useful in a loop:

while ( /\w+/g ) {
   say $&;
}

We can use pos to we can see what's going on.

local $_ = "abc def ghi";
while ( ( say pos // 0 ), /\w+/g ) {
   say $&;
}
0
abc
3
def
7
ghi
11

But while this is useful in a loop, it it makes no sense as if ( //g ) (unless you're unrolling a loop). What would it mean? "Check if it matches, and keep checking for more matches for no reason"??? Obviously, that makes no sense. Remove the g to prints yes twice.

like image 200
ikegami Avatar answered Sep 06 '26 04:09

ikegami



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!