I have several regexp with capturing and obviously the capturing variable retains the value of the last valid capturing:
# Two scalars to use for regexp
$x = 'abc';
$y = 'def';
# first regexp
$x =~ /^(ab)/;
$x = $1;
# second regexp
$y =~ /^(de)/;
$y = $1;
print \"$x\n$y\";
The output is:
ab
de
Here the one-liner version:
perl -e "$x='abc'; $y='def'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"
If $y='def'
is changed to $y='zdef'
:
perl -e "$x='abc'; $y='zdef'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"
the output is:
ab
ab
If I want to set $1=undef
after $x=$1
to remove the current value in $1
perl -e "$x='abc'; $y='zdef'; $x =~ /^(ab)/; $x=$1; $1=undef; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"
the output is:
Modification of a read-only value attempted at -e line 1.
Obviously, capturing variables can't be changed.
I'm wondering how I can cope with this problem. The result I would like to have is:
ab
..
where ..
means "empty". Like in this case where the first regexp is undef ($x='zabc
):
perl -e "$x='zabc'; $y='def'; $x =~ /^(ab)/; $x=$1; $y =~ /^(de)/; $y=$1; print \"$x\n$y\";"
..
de
You need to use the capture variables $1
(and $2
, $3
, etc) carefully. They are assigned at successful pattern matches (and unassigned), so you have to make sure you have the right match.
man perlvar
states (the emphasis is on successful):
$<digits> ($1, $2, ...)
Contains the subpattern from the corresponding set of capturing
parentheses from the last successful pattern match, ...
Typically, you would do this:
if ('abc' =~ /^(ab)/) {
$x = $1;
}
if ('zdef' =~ /^(de)/) {
$y = $1;
}
This way, you never get the wrong value assigned.
There are, however, other ways to do this. The pattern match itself gives a return value, which depends on the context.
$n = 'abc' =~ /^(ab)/; # $n = 1 for "true". This is scalar context
($n) = 'abc' =~ /^(ab)/; # $n = 'ab', the captured string. This is list context
$n = () = 'abc' =~ /(.)/g; # $n = 3, for 3 matches. /g gives multiple matches
($f, $g) = 'abc' =~ /(.)/g; # $f = 'a', $g = 'b'. List context