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

What is wrong with my matching? It SHOULD work because we are looking for the phrase 11 in the array and it exists, so what's going wrong? This was a test I threw up because my real problem is messing with anonymous arrays trying to get a whole list of tests to pass.

One other question, if I am testing @text with many things, is there a shorter way to write it than copy and pasting the variable name each time?

#!/usr/bin/perl my @text = ("Hi there 11", "Fred blamed me", "17 o clock", "It's snowi +ng hampsters", "Pickles are people too!"); if (@text =~ /11/ || @text =~ /are/) { print "test successfull"; } else { print "We messed something up again";};

Replies are listed 'Best First'.
Re: Matching arrays?
by BrowserUk (Patriarch) on Mar 06, 2004 at 11:53 UTC

    Regexes work on scalars (individual variables), not on whole arrays at a time.

    However, perl comes to the rescue with it's built-in grep function

    #! perl -slw use strict; my @text = ( "Hi there 11", "Fred blamed me", "17 o clock", "It's snowing hampsters", "Pickles are people too!" ); if ( grep( /11/, @text ) || grep( /are/, @text ) ) { print "test successfull"; } else { print "We messed something up again"; }; __END__ P:\test>334482 test successfull

    This asks grep to scan each element in the array and pass through only those that match the regex.

    However, in a scalar context, it returns not the elements themselves, but a count of those that matched. If the number matched is non-zero, then the if statement will be true.

    Once you've got that working, you will see that there is no need to scan the whole array twice, as you can put both regexes into the same grep and look for them both in one pass.

    if ( grep( /11/ || /are/, @text ) ) { print "test successfull"; } else { print "We messed something up again"; };

    In this case, it is also possible to remove the need to match against each string twice, by combining the search terms into a single regex.

    if ( grep( /(11|are)/, @text ) ) { print "test successfull"; } else { print "We messed something up again"; };

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
      It should be noted that grep(/11/||/are/,@text) will be quite a bit faster in execution than grep(/11|are/),@text) because of the short circuit and constant regexpes.

      Indeed, after a quick test I found:
      #!/usr/bin/perl use Benchmark qw(timethese cmpthese); my @seed = ("Hi there 11", "Fred blamed me", "17 o clock", "It's snowi +ng hampsters", "Pickles are people too!"); @text = map {@seed[$_ % $#seed+1]}(0 .. 300); cmpthese -1 => { short_circuit => 'grep(/11/||/are/,@text)', alternate => 'grep(/11|are/,@text)', } __END__ bagelbox:~ josh$ perl testgrep Rate alternate short_circuit alternate 642/s -- -81% short_circuit 3309/s 416% --
        I'd think that after a certain number of alternates the regex would be faster.
      Weird, I just tried writing a full string of text with numbers in it and I tried using the same expression I wrote in my original node (except I used a scalar instead of array) and it still failed. If making multiple tests to see if atleast one of a few phrases are present in a string, what's wrong with my original code?
        what's wrong with my original code

        You original code below:
        if (@text =~ /11/ || @text =~ /are/) { ...

        Ok, the problem with your code is that you are operating the array text in scalar context, which is the number of elements in the array. So you code is actually doing this:
        if ('5' =~ /11/ || '5' =~ /are/) { ...

        And of cause it will not match anything.

        and it still failed.

        Please show us the code.

        What you are saying is the following:

        my $text = "Hi there 11 Fred blamed me 17 o clock It's snowing hampste +rs Pickles are people too!; if ($text =~ /11/ || $text =~ /are/) {

        This snippet will work. What did you do?

        #!/usr/bin/perl use strict; my $check; my @text = ("Hi there 11", "Fred blamed me", "17 o clock", "It's snowi +ng hampsters", "Pickles are people too!"); foreach (@text) { if ( /11/ || /are/) { print "test successful"; $check++; } } unless ($check) { print "test failed"; }
        of course you should also use strict!!