upallnight has asked for the wisdom of the Perl Monks concerning the following question:

Every time I run this code, the string "pmos_lkg" does not get matched in the string $ModNameList.
Is there a bug in m//? It can't be a size issue because strings after this one get matched.
It also seems to be independent of the string, meaning if I sort @files differently, a different string will not get matched.
I would really appreciate it if someone could help me solve this!

foreach $files ( @files ) { if( $files =~ m/.output/gi ) { my $name = $files; $name =~ s/.output//gi; $name =~ s/^cqa_//gi; if($ModNameList =~ m/$name/g) { print "Found:$name\n"; } } }

Replies are listed 'Best First'.
Re: Pattern Matching Failing
by jwkrahn (Abbot) on Sep 30, 2007 at 01:59 UTC
    if($ModNameList =~ m/$name/g) {

    You are using the /g global option in scalar context so the regular expression keeps track of the current position in the string for the next match thereby bypassing matches that are to the left of the current match.

    None of the patterns in your example require the use of the /g option.

Re: Pattern Matching Failing
by johngg (Canon) on Sep 30, 2007 at 08:08 UTC
    Be aware that the dot, ".", is a regular expression metacharacter meaning match any character (with a caveat, have a look at perlre). If you want to match the literal ".output" but not, say, "toutput" then you need to escape the dot with a backslash.

    $name =~ s/\.output//i;

    I hope this is of use.

    Cheers,

    JohnGG

Re: Pattern Matching Failing
by throop (Chaplain) on Sep 30, 2007 at 15:20 UTC
    Gentle upallnight,

    jwkrahn is right that the 'g's are superfluous. But I don't think that is the core of the problem. Indeed, if that had been the problem, the match would have always failed. You are invoking s///g in a void context, not a scalar one. Indeed, after a mild cleaning of your code, I can't reproduce the problem as described:

    #!/usr/local/bin/perl -w use strict; my @files =qw(CQA_frobbish.OUTPUT cQa_blintz.output cqA_pmos_lkg.outpu +t); my $ModNameList = 'pmos_lkg'; foreach my $file ( @files ) { if($file =~ m/.output/gi ) { my $name = $file; $name =~ s/.output//gi; $name =~ s/^cqa_//gi; if($ModNameList =~ m/$name/g) { print "Found:$name\n"; } } }
    prints
    Found:pmos_lkg
    Some other comments on your code:
    • use strict; Your code will be better and you'll get more help. We don't like debugging code when it turns out that the problem is some minor spelling error. Really, this is a monastery and using strict is a religious matter around here.
    • Don't have a scalar $files and an array @files. It's just confusing and a potential source of error.
    • You don't need to successively trim the $name string. A pattern match out of the loop variable would give you all you need. The 'x' modifier allows us to comment the pattern match.
      use strict; foreach (@files){ my $name2; if(($name2) = / ^cqa_ # Starts with cqa_ (.*) # Here's the namestring we want \.output # and the right file extenstion $/xi # and nothing else. and $ModNameList =~ /$name2/){ print "FOUND: $name2\n"}}
    throop
      Thanks. If I use strict with this script, it gets stuck in some kind of infinite loop.

      I'm still having a problem with this code, but its behaving differently now:
      The second matching if statement returns 1 for every $file except cqa_cqa_testcase_allpass.output and cqa_cqa_testcase_allfail.output.

      What I am trying to do is create a new array from @files, filtering the elements to contain only those which are found in the $ModNameList string.

      Using this string and array:
      my $ModNameList = ",cqa_16k_otp_array_a.output,cqa_4x4k_otp_array_b.ou +tput,cqa_BOAC_TEST_1.output,cqa_IPA_WLR_01_1P0.output,cqa_IPA_WLR_02_ +1P0.output,cqa_IPA_WLR_03_1P0.output,cqa_IPA_WLR_04_1P0.output,cqa_IP +A_WLR_05_1P0.output,cqa_IPA_WLR_06_1P0.output,cqa_ac_1.output,cqa_ac_ +10.output,cqa_ac_11.output,cqa_ac_12.output,cqa_ac_13.output,cqa_ac_1 +4.output,cqa_ac_15.output,cqa_ac_16.output,cqa_ac_2.output,cqa_ac_3.o +utput,cqa_ac_4.output,cqa_ac_5.output,cqa_ac_6.output,cqa_ac_7.output +,cqa_ac_8.output,cqa_ac_9.output,cqa_antenna_m1tn.output,cqa_antenna_ +m2tn.output,cqa_antenna_nmos_dea_hvg.output,cqa_antenna_nmos_dea_lvg. +output,cqa_antenna_npn.output,cqa_antenna_pmos_dea_hvg.output,cqa_ant +enna_pmos_dea_lvg.output,cqa_antenna_pmos_thin_gate.output,cqa_antenn +a_pnp.output,cqa_antenna_tin_ply.output,cqa_asetsafsda.output,cqa_bip +_mismatch.output,cqa_bjt_singles.output,cqa_bjtmtch_ctchn_1.output,cq +a_bjtmtch_ctchn_10.output,cqa_bjtmtch_ctchn_11.output,cqa_bjtmtch_ctc +hn_12.output,cqa_bjtmtch_ctchn_2.output,cqa_bjtmtch_ctchn_3.output,cq +a_bjtmtch_ctchn_4.output,cqa_bjtmtch_ctchn_5.output,cqa_bjtmtch_ctchn +_6.output,cqa_bjtmtch_ctchn_7.output,cqa_cqa_testcase_allfail.output, +cqa_cqa_testcase_allpass.output,cqa_ctop_a.output,cqa_ctop_b.output,c +qa_ctopm1_a.output,cqa_ctopm1_b.output,cqa_ctopm2_a.output,cqa_ctopm2 +_b.output,"; my @files = (cqa_16k_otp_array_a.output","cqa_4x4k_otp_array_b.output" +,"cqa_BOAC_TEST_1.output","cqa_IPA_WLR_01_1P0.output","cqa_IPA_WLR_02 +_1P0.output","cqa_IPA_WLR_03_1P0.output","cqa_IPA_WLR_04_1P0.output", +"cqa_IPA_WLR_05_1P0.output","cqa_IPA_WLR_06_1P0.output","cqa_ac_1.out +put","cqa_ac_10.output","cqa_ac_11.output","cqa_ac_12.output","cqa_ac +_13.output","cqa_ac_14.output","cqa_ac_15.output","cqa_ac_16.output", +"cqa_ac_2.output","cqa_ac_3.output","cqa_ac_4.output","cqa_ac_5.outpu +t","cqa_ac_6.output","cqa_ac_7.output","cqa_ac_8.output","cqa_ac_9.ou +tput","cqa_antenna_m1tn.output","cqa_antenna_m2tn.output","cqa_antenn +a_nmos_dea_hvg.output","cqa_antenna_nmos_dea_lvg.output","cqa_antenna +_npn.output","cqa_antenna_pmos_dea_hvg.output","cqa_antenna_pmos_dea_ +lvg.output","cqa_antenna_pmos_thin_gate.output","cqa_antenna_pnp.outp +ut","cqa_antenna_tin_ply.output","cqa_asetsafsda.output","cqa_bip_mis +match.output","cqa_bjt_singles.output","cqa_bjtmtch_ctchn_1.output"," +cqa_bjtmtch_ctchn_10.output","cqa_bjtmtch_ctchn_11.output","cqa_bjtmt +ch_ctchn_12.output","cqa_bjtmtch_ctchn_2.output","cqa_bjtmtch_ctchn_3 +.output","cqa_bjtmtch_ctchn_4.output","cqa_bjtmtch_ctchn_5.output","c +qa_bjtmtch_ctchn_6.output","cqa_bjtmtch_ctchn_7.output","cqa_cqa_test +case_allfail.output","cqa_cqa_testcase_allpass.output","cqa_ctop_a.ou +tput","cqa_ctop_b.output","cqa_ctopm1_a.output","cqa_ctopm1_b.output" +,"cqa_ctopm2_a.output","cqa_ctopm2_b.output);

      This code creates @cqa_status with all the files except cqa_cqa_testcase_allpass.output and cqa_cqa_testcase_allfail.output.
      my @cqa_status; foreach my $file ( @files ) { if($file =~ /^cqa_(.*)\.output$/i) { my $name = $file; $name =~ s/^cqa_//i; $name =~ s/\.output$//i; if( $ModNameList =~ /^(.*),$name,(.*)$/ ) { print "Matched $name:" . ($ModNameList =~ /^(.*),$name,(.* +)$/) . "<br>\n"; push(@cqa_status, $file); } } }

      Substituting if( $ModNameList =~ /^(.*),$name,(.*)$/ ) { for if( !($ModNameList =~ /^(.*),$name,(.*)$/) ) { does the opposite
      and creates @cqa_status only containing cqa_cqa_testcase_allpass.output and cqa_cqa_testcase_allfail.output.
      my @cqa_status; foreach my $file ( @files ) { if($file =~ /^cqa_(.*)\.output$/i) { my $name = $file; $name =~ s/^cqa_//i; $name =~ s/\.output$//i; if( $ModNameList =~ /^(.*),$name,(.*)$/ ) { print "Matched $name:" . ($ModNameList =~ /^(.*),$name,(.* +)$/) . "<br>\n"; push(@cqa_status, $file); } } }

      I thought I understood regex, but this doesn't make sense to me.
      Right now, it should match every $file from $ModNameList and if @files grows
      it should filter @files to $ModNameList so scalar(@files) should always be the
      same number at the end of this code.