sfoy sfoy - 1 month ago 5
Perl Question

Counting Strings in Regexs After A Conditional in Perl

Storing all matching strings in an array in Perl does not seem to work correctly if I do it after a simple conditional involving the query string. Does anyone know why this is? I have some code below that illustrates this:

#!/usr/local/bin/perl -w

use warnings;
use strict;

my ($string,
@instance_array,
);

$string = 'ABCDCECFCG';
print "String: $string\n\n";

# PRINT INSTANCE ARRAY BEFORE CONDITIONAL
@instance_array = $string =~ m/C./g;
print "BEFORE CONDITIONAL\n@instance_array\n"; print scalar @instance_array; print "\n\n";
undef @instance_array;

##############################################

#if (@instance_array = $string =~ m/C./g)
if ($string =~ m/C./g)
{
# PRINT INSTANCE ARRAY INSIDE CONDITIONAL
print "INSIDE CONDITIONAL\n@instance_array\n"; print scalar @instance_array; print "\n\n";
};

print "String: $string\n\n";
undef @instance_array;

############################################

# PRINT INSTANCE ARRAY AFTER CONDITIONAL
@instance_array = $string =~ m/C./g;
print "AFTER CONDITIONAL\n@instance_array\n"; print scalar @instance_array; print "\n\n";
undef @instance_array;

# PRINT FINAL INSTANCE ARRAY
@instance_array = $string =~ m/C./g;
print "AFTER CONDITIONAL\n@instance_array\n"; print scalar @instance_array; print "\n\n";
undef @instance_array;

exit;


Notice that the "BEFORE CONDITIONAL" @instance_array output is correct (i.e., there are four matches for the regex), the one inside the conditional is undefined (as it should be), but the "AFTER CONDITIONAL" @instance_array is missing the "CD" match. Also notice that the "FINAL" @instance_array is also correct, even though it is the exact same code as that used to print the "AFTER CONDITIONAL" @instance_array.

According to the $string print statement after the conditional, the conditional does not appear change the query $string in any way.

Another interesting thing to note: If I send all the matches to the @instance_array in the simple conditional (this line is commented out above the simple conditional), then all four matches are correctly placed in the array.

Does anyone know why the initial match ("CD") is not entering the @instance_array? Perhaps it is storing the "CD" match in an internal variable (like $1, even though I know this is not quite correct) and not properly reinitializing it after the conditional?

Thank you for your help everyone.

Answer

Just remove /g in your condition i.e.:

if ($string =~ m/C./g)

For the if condition you shouldn't use /g. This is because it's changing the pos of the regex. You can use it, though, e.g. in while loop.

To see how it's being changed you can print it after that if statement:

print pos $string;

You will see that it's changed to 4. To reset the pos:

pos($string) = 0;

However, it's not recommended. Just don't use /g in the if.

Comments