Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl subtitute not working after previous pattern match

Tags:

perl

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?

like image 245
user2676847 Avatar asked Aug 16 '14 12:08

user2676847


1 Answers

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/
like image 123
Borodin Avatar answered Sep 19 '22 10:09

Borodin