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

Hello monks,

I've looked through the documentation and the internet, but found no answer so far, so here is my question.

I've got an array, say (a, b, c, d), and i've got a file, which contain lines which will on won't match with one of the array elements.
So, I'm looking for a shorter and more efficient way to match the lines with the array elements than a foreach() (or a for() for what that matters), like

my @array = qw(a b c d); open(my $file, myfile.txt); while (<$file>) { if ($_ =~ $array[0..$#array]) { ## instead of: foreach(@array) print "Matches!\n"; } }

As i already tested by myself, the match part won't work, so any help will be appreciated (if there's of course a solution, otherwise i'll surrend and use a foreach().

Thanks in advance

Replies are listed 'Best First'.
Re: Regex and array
by Corion (Patriarch) on May 25, 2010 at 10:11 UTC

    Are you sure that the match part won't work? Have you checked that you can open your file and read the lines you expect?

    Adding the line

    use strict;

    to the top of your script will make Perl tell you what it sees. Then you will find that what you see is not what Perl sees.

    You should always guard your calls to open with an or die like this:

    open my $file, $filename or die "Couldn't open '$filename': $!";

    That way, you prevent your program from running when it can't read a file and you even get an informative error message.

      Hi Corion and everyone

      thanks in advance for your answer. The problem is not that it can't read the file. The lines i posted above where just there for shorten the problem. I usually put the "use strict" pragma and the die() instruction in my scripts to prevent what you correctly pointed out.

      This time, indeed, the problem is that if I try to match the array's elements without cycling them with a foreach, I can't get a match.

      I'll try to post a maybe better example

      #!/usr/bin/perl my @array = qw( ciccio paperino palla gigio pluto ); my $test = pluto; if ( $test =~ $array[0..$#array] ) { print "It matched!\n"; }
      didn't work for me. Is the syntax wrong? Am I missing something? Thanks again for your help.
        Am I missing something?
        Yes, you are ignoring important warnings because you did not use strict and warnings.

        One way to search an array for a specific value is to use grep. I think you are looking for something like this:

        use strict; use warnings; my @array = qw( ciccio paperino palla gigio pluto ); my $test = 'pluto'; if (grep { $test eq $_ } @array ) { print "It matched!\n"; }

        You are making up Perl syntax and expect it to work. I don't think that array slices and the =~ operator are documented to do anything sensible.

        Again, you are not using strict. You should really get into the habit of doing that.

        If you are using Perl 5.10 or newer, you might be able to put the "smart match" operator (~~) to work. See perlop on it. Otherwise, you could use grep to search through the array.

        I've used the following technique successfully for this kind of situation. It compiles the regex only once, so it can be reused efficiently in a loop:
        my @array = qw( ciccio paperino palla gigio pluto ); my $TestReStr = join("|", map { "(${_})" } @array); my $TestRe = qr/$TestReStr/; my $test = 'pluto'; print "It matched!\n" if $test =~ $TestRe ;
Re: Regex and array
by baxy77bax (Deacon) on May 25, 2010 at 10:52 UTC
    hi,

    if you tested negative for corion's explanation which is usually the case(people usually tend to open a file that does not exists), try this:

    #!/usr/bin/perl use strict; my @array = qw(q e t u o); while(<DATA>){ chomp(my $r = $_); grep{print "$_\n" if ($r =~ /$_/g)}@array; } __DATA__ ff qksjnfji klksnsd jkksdjen rjkaa
    i always use grep or map when going through arrays or hashes, try it, it's a lot of fun !

    cheers

      grep{print "$_\n" if ($r =~ /$_/g)}@array;
      • There is no need for the //g modifier.
      • I would not advocate this usage of grep. You are ignoring its return value. I think a for loop would be more straightforward in this case:
      for (@array) { print "$_\n" if ($r =~ /$_/); }

      Thanks baxy77bax for your suggestions.

      I applied it in the shape that you and toolic suggested, and it worked!

      Thanks again for your precious help!