I have a strange problem that the susbtitute operator s///
doesn't work after a preceding pattern match. For example
use strict;
use warnings;
my $var = "var";
$var =~ s||/|g;
print "$var\n";
The output is: /v/a/r/
But in this case
use strict;
use warnings;
my $a = "test";
if ($a =~ /te/) {
my $var = "var";
$var =~ s||/|g;
print "$var\n";
}
the output is: var
, when it should be the same as the previous result.
What is going on here? How can I fix it?
perlop
has this to say about the The empty pattern //
If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead. In this case, only the g and c flags on the empty pattern are honored; the other flags are taken from the original pattern. If no match has previously succeeded, this will (silently) act instead as a genuine empty pattern (which will always match).
So your first case does a substitution on the empty string because there have been no previous pattern matches, while the second comes after a successful match of te
in test
, so it substitutes te
everywhere in var
and so has no effect.
This program demonstrates
use strict;
use warnings;
my $str = 'a/b/c';
if ($str =~ m{/}) {
$str =~ s//x/g;
}
print $str;
output
axbxc
The only exception to this is the pattern in the split
command, which always matches an empty pattern if that is what you specify.
To get around this, if you really want to match the point before and after every character, you can use the /x
modifier to use an insignificant space for your pattern, like this
use strict;
use warnings;
my $var_a = 'test';
if ($var_a =~ /te/) {
my $var_b = 'var';
$var_b =~ s| |/|gx;
print "$var_b\n";
}
output
/v/a/r/
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