Jeff Sims Jeff Sims - 5 months ago 11
Perl Question

Perl regex not working on variable after it has already matched a previous regex

Please help me figure out why the following does not work like I expect it to. I should be able to skip all of the array items that don't match and then match on any of the ones that get through. Instead, I have to make a copy of the for loop variable $server and match on it after it has been matched by one regex and let through.The variable $server still contains the same string and I would expect to be able to match it to a second regex:

use strict;
use warnings;
use diagnostics;

@servers = ('server01', 'server02', 'vm13', 'vm02');

for my $server ( @servers) {

if ($server !~ m/server01|vm13|vm02/ig ) {

next;

} else {
say $server; # It will print string that contains
# server01, vm13, or vm02

if ($server =~ m/server01/ig) {

say $server # It will not print string that
# contains server01 here
}

say $server, " again..."; # The variable still works here
}


This way does work:

use strict;
use warnings;
use diagnostics;

@servers = ('server01', 'server02', 'vm13', 'vm02');

for my $server (@servers) {

my $server_copy = $server;

if ($server !~ m/server01|vm13|vm02/ig ) {

next;

} else {

say $server; # It will print the name of the server
# that contains server01, vm13, or vm02

if ($server_copy =~ m/server01/ig) {
say $server # It now prints the name of that server
}

say $server, " again..."; # The variable still works here
}


Any help would be appreciated.

Answer

In short, it's the global modifier /g in the regex that causes the behavior you see.

I've changed the code a bit around as well.

use strict;
use warnings;
use diagnostics;

my @servers = ('server01', 'server02', 'vm13', 'vm02');

foreach my $server ( @servers) {

    next if not $server =~ m/server01|vm13|vm02/i;

    say $server;  # Prints string with either server01, vm13, or vm02

    if ($server =~ m/server01/i) {
        say "=> Looking for: $server";
    }   

    say "$server, again..."; # The variable still works here
}   

Note that if the list of servers to keep grows longer you can make use of functions like any from the List::MoreUtils package.