if ( $contents =~ /line3/g ) {
if ( $contents =~ /(line2-)(\w*)/g ) {
print $2;
}
}
In $contents is the slurped file:
line1-11
line2-12
line3-13
The first if matches
'line3' and returns true. The second match picks up at the
position where the first match left (because it has also the
/g modifier) and fails (!) because line2 is before line3.
So removing the /g modifier on the second 'if' solves the
problem as the match is now done from the start of $contents.
As a matter of fact, the /g modifier can be left out for
both matches.
Some further optimisations I would suggest for this
regex:
- Leave out the capturing brackets for (line2-)
- Use multiline matching (/m)
- Compile the patterns only once (/o)
This then leads to the following code:
if ( $contents =~ /^line3/mo ) {
if ( $contents =~ /^line2-(\w*)/mo ) {
print $1; # has to be changed as well
}
}
To clarify the /g modifier a little bit further let's take
a look at
this code (of course see also perlre and perlop):
my $string = "abcde abcde adcde";
while ($string =~ /cd/og) {
print "pos = ", pos $string, "\n";
if ($string =~ /a(.)/ocg) {
print "a$1 matched at ",pos $string, "\n";
}
}
Here the first match happens in a while loop, but
important still in scalar context. The inner matching starts
at the position where the first left off as it also has the
/g modifier. Then the outer match takes its turn again
starting where the inner left off. The position in the string
is only reset when a match fails. This does not happen when
the /c modifier is given. This is necessary for the second
match in this case - otherwise there is an infinite loop.
Taking this code and playing a bit with the modifiers and
the string helps a lot in understanding these (not so
easy) things.
And I haven't even started talking about m//g in list
context yet ...
-- Hofmator
|