Is there a way to do this without getting an infinite loop?
while((my $var) = $string =~ /regexline(.+?)end/g) {
print $var;
}
This results in an infinite loop, probably because the assigning of a var directly from a regex inside the while returns "true" every time?
I know I can do this:
while($string =~ /regexline(.+?)end/g) {
my $var = $1;
print $var;
}
But I was hoping I could save a line. Is there a regex modifier I can use or something like that?
(Also, what is this notation/trick actually called, if I want to search for it:
(my $var) = $string =~ /regex/;
Thanks!!
In scalar context, a regular expression with the /g
modifier will act like an iterator and return a false value when there are no more matches:
print "$1\n" while "abacadae" =~ /(a\w)/g; # produces "ab","ac","ad","ae"
With the assignment inside the while
expression, you are evaluating your regular expression in list context. Now your regular expression doesn't act like an iterator anymore, it just returns the list of matches. If the list is not empty, it evaluates to a true value:
print "$1\n" while () = "abacadae" =~ /(a\w)/g; # infinite "ae"
To fix this, you can take the assignment out of the while statement and use the builtin $1
variable to make the assignment inside the loop?
while ($string =~ /regexline(.+?)end/g) {
my $var = $1;
print $var;
}
Is there a way to do this without getting an infinite loop?
Yes. Use a foreach() instead of a while() loop:
foreach my $var ($string =~ /regexline(.+?)end/g) {
what is this notation/trick actually called, if I want to search for it
It is called a match in list context. It is described in "perldoc perlop":
The g modifier specifies global pattern matching--that is, matching as many times as possible within the string. How it behaves depends on the context. In list context ...
The Perl regular expressions tutorial says:
In scalar context, successive invocations against a string will have //g jump from match to match, keeping track of position in the string as it goes along.
But:
In list context, //g returns a list of matched groupings, or if there are no groupings, a list of matches to the whole regexp.
That is to say, in list context //g
returns an array of all your captured matches at once (of which you subsequently discard all but the first), and then does that all over again every time your loop executes (i.e. forever).
So you can't use the list context assignment in a loop condition, because it doesn't do what you want.
If you insist on using the list context, you could do this instead:
foreach my $var ($string =~ /regexline(.+?)end/g) {
print $var;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With