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

I has a minor problem. I want to test if any of a series of regular expressions matches a string. If there is a match I want to print the expression. I achieved this fairly easily using a foreach..
foreach $pattern (@patterns)) { if ($input =~ /$pattern/) { print $pattern; } }
However, commonsense tells me that if theres a large number of patterns thats going to be really slow. Is there, in the classic Perl sense, another way to do it?
Chris
$live{$free}||die

Replies are listed 'Best First'.
Re: More than one regexp.
by danger (Priest) on Jan 19, 2001 at 19:51 UTC

    Well, most people have pointed out the qr// operator, but didn't notice that you wanted to print your re's if matched, not the input. However, you can still speed up your matching by using qr//:

    #!/usr/bin/perl -w use strict; my @patterns = qw/ ^foo bar x.*?z /; @patterns = map{qr/$_/}@patterns; my $input = 'fooxbaz'; foreach my $re (@patterns){ print "$re\n" if $input =~ /$re/; }

    The re's you get back aren't exactly the same as the pattern strings originally provided (notably they'll have '(?-ixsm)' appended to them to indicate which modifiers were present (or not in this case) when compiled).

Re: More than one regexp.
by I0 (Priest) on Jan 19, 2001 at 15:27 UTC
Re: More than one regexp.
by RatArsed (Monk) on Jan 19, 2001 at 14:34 UTC
    My feeling would be to try something like:
    my $patternlist = join( "\t", @patterns ); if( $patternlist =~ /\t$input(.*)\t/ ) { print $input.$1; }
    NB This will do something akin to "command matching"

    If you wanted to match whole patterns only, then:

    my $patternlist = join( "\t", @patterns ); if( $patternlist =~ /\t$input\t/ ) { print $input; }
    of course RatArsed

      The problem with this is that you have to compile a new regular expression for every line of $input. You can do this sort of alternation in a regular expression like

      my @patterns = qw/ test good /; my $alt = join('|', @patterns); my $re = qr/(?:$alt)/; while (<DATA>) { if ( /$re/ ) { print "+ $_"; } else { print "- $_"; } } __END__ THis is a test this is only a test now is the time for all good men to come to the aid of their country.

      Other than perlop and perlre, a good place to look for regular expressions is the Jeffery Friedl book, Mastering Regular Expressions.

        Assuming that your target strings don't change, tack a /o onto the assembled regexp invocation to compile it once. (See perlre for details.)
Re: More than one regexp.
by kschwab (Vicar) on Jan 19, 2001 at 18:46 UTC
    You may also want to have a look at study