http://qs321.pair.com?node_id=150681

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

I have an array of regexps quoted in single quotes:    @a = ('hello(\w+)', ...); and I have a scalar value that I want to compare against all the regexps to see if it matches one of them:
$a = "Hello(world)"; $b = shift(@a); if ($a =~ /$b/o) { print "Matched!\n"; }
Never can get it to match.

So then I tried modifying my array as follows:    @a = ('hello\((\w+)\)', ...); And tried again to no avail. Help...

Added code tags - dvergin 2002-03-10

Replies are listed 'Best First'.
(ar0n) Re: Need help comparing against a set of regexps
by ar0n (Priest) on Mar 10, 2002 at 07:11 UTC
    my @regexes = map qr/$_/, ('hello(\w+)', 'HELLO(\w+)', Hello(\w+)'); for my $re (@regexes) { if ($string =~ $re) { print "$string matched $re\n"; } }

    [ ar0n -- want job (boston) ]

      Is there a way to do this in Perl5? I don't have the qr// thing.

        qr was added in Perl 5.005_03. If you're running anything older than that, you should consider an upgrade, as previous versions are considered buggy.


        my @regexes = ('HELLO(\w+)', 'hello(\w+)', 'Hello(\w+)'); for my $re (@regexes) { $re =~ s!/!\/!; # escape delimiters my $eval = '$string =~ /' . $re . '/;'; if ( eval $eval ) { print "$string matches $re\n"; } }
        It's an ugly hack, and I would very much prefer it if you would promote world peace, fight hunger and help stop global warming by upgrading your version of Perl.

        [ ar0n -- want job (boston) ]

Re: Need help comparing against a set of regexps
by seattlejohn (Deacon) on Mar 10, 2002 at 08:09 UTC
    You don't want the "o" suffix on your regex. In if ($a =~ /$b/o), the "o" is making a promise that you won't change the value of $b, so perl doesn't recompile the regex for each $b you create. You probably do want the "i" suffix to make the matching case-insensitive -- otherwise 'Hello' will not match 'hello'! Consider this a starting point:
    'Hello(world)' =~ m/hello\(\w+\)/i  # is true

    Replace the right side with the variable containing the current regex you want to match and you will be on your way.

    BTW, it's generally a good idea to avoid using the variable names $a and $b because they have a special significance to perl (see perldoc -f sort).

Re: Need help comparing against a set of regexps
by gellyfish (Monsignor) on Mar 10, 2002 at 10:13 UTC

    You can cut out the loop by doing something like:

    my @regexes = ('hello(\w+)','foo(\d+)','zubbble(.*)'); my $re = join '|', sort { length $b <=> length $a } @regexes; $re = "(?:$re)"; print "Matched!\n" if 'foo123' =~ /$re/;
    Check out the perlre manpage for more on how this works.

    /J\

Re: Need help comparing against a set of regexps
by Juerd (Abbot) on Mar 10, 2002 at 12:34 UTC

    @a = ('hello(\w+)', ...); and I have a scalar value that I want to compare against all the regexps to see if it matches one of them: $a = "Hello(world)"; $b = shift(@a); if ($a =~ /$b/o) { print "Matched!\n"; }

    "helloworld" =~ /hello(\w+)/ is a match, with world in $1.
    "hello(world)" =~ /hello(\w+)/ doesn't match, because the opening paren is not \w.

    "Hello" =~ /hello/ doesn't match, because H and h are different. Use the /i modifier.

    To overcome the first problem, you must escape the parens, so they will match literal parens, and no longer have a special meaning:

    my @foo = ('hello\(\w+\)', ' ... '); my $foo = "Hello(world)"; for my $bar (@foo) { print "Matched ($foo, $bar)\n" if $foo =~ /$bar/i; }


    A better approach would be using qr/hello\(\w\)/ in the list assignment and $foo =~ $_ as the match, but that requires a recent version of perl.

    44696420796F7520732F2F2F65206F
    7220756E7061636B3F202F6D736720
    6D6521203A29202D2D204A75657264
    

Re: Need help comparing against a set of regexps
by strat (Canon) on Mar 10, 2002 at 21:41 UTC
    If you want to match a string against many different patterns, it could give an improvement in performance if you "study" your variable before the matchings...

    perldoc -f study

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"