sfoy
sfoy

Reputation: 23

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.

Upvotes: 2

Views: 93

Answers (3)

Andre Carneiro
Andre Carneiro

Reputation: 736

About your regex "/C./"

This certainly will be a problem because you're not restricting the regex criteria. The character '.' as you're using means "literally" anything to Perl regex engine. Now, supposing that you're trying to find the character '.', you must escape the "." character inside your regex statement like this:

/^C\.$/

If you want to capture the "matches", you must mark what you want to bring from each match with groups between parenthesis. Something like that:

/(whatever)(foo)(bar)/

Matches results in Perl are stored in special variables and are submited to scope rules. Some variables are $_, $1, $2,..., "$n" when '$n' is the nth group defined inside the regular expression, and is just "illustrative" and doesn't exists as special variable in fact. Considering the example above:

my $string = "Perl regex rocks!";
my ($match1, $match2, $match3) = ($1,$2,$3) if $string =~ /^(\w+)\s(\w+)\s(\w+)!$/;

#$match1 = "Perl"
#$match2 = "regex"
#$match3 = "rocks"

Links of Perl regular expression:

http://perldoc.perl.org/perlre.html

http://perldoc.perl.org/perlreref.html

Beautiful book about Regular expressions(tons of examples in Perl)

http://shop.oreilly.com/product/9780596528126.do

Upvotes: 0

EvilArtist
EvilArtist

Reputation: 1

try this:

my @matches = ($string =~ /(regex)/g);

Upvotes: 0

dbosky
dbosky

Reputation: 1641

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.

Upvotes: 2

Related Questions