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

I would like to take an array full of regular expressions and match a string against it. The code below does not work but shows what I am trying to do.
#!/usr/bin/perl -w use strict; my $string = "Field1: one"; my @regex; push(@regex, 'm/Field1: (\w{3})/'); push(@regex, 'm/Field2: (\w{3})/'); push(@regex, 'm/Field3: (\w{3})/'); foreach $_ (@regex) { $string =~ $_; print "$1\n" if defined $1; }
Is it possible to do something like this? Thanks in advance!

Replies are listed 'Best First'.
Re: RegEx Array
by Enlil (Parson) on Apr 12, 2004 at 05:45 UTC
    I think this is what you want:
    #!/usr/bin/perl -w use strict; my $string = "Field1: one"; my @regex; push(@regex, qr/Field1: (\w{3})/); push(@regex, qr/Field2: (\w{3})/); push(@regex, qr/Field3: (\w{3})/); foreach (@regex) { if ($string =~ $_ ) { print "$1\n"; } }
    Note that I changed the conditional in the foreach loop so that it would print only if the match was successful rather than in $1 was defined, which in this case after the first match continues to be defined.

    -enlil

Re: RegEx Array
by davido (Cardinal) on Apr 12, 2004 at 05:43 UTC
    my $string = "Field1: one"; foreach my $reobj ( qr/Field1/, qr/Field2/, qr/Field3/) { print "$1\n" if $string =~ m/$reobj: (\w{3})/; }

    Basically you can take advantage of the aliasing feature of foreach loops to help in creating your multiple re's. Another alternative would be simple alternation.

    Update: To more specifically address your question, there's no reason why you couldn't put the regular expressions into an array like this:

    my $string = "Field1: one"; my @regexobjs = ( qr/Field1/, qr/Field2/, qr/Field3/ ); foreach my $reobj ( @regexobjs ) { # The rest is the same as above.....


    Dave

Re: RegEx Array
by tachyon (Chancellor) on Apr 12, 2004 at 06:54 UTC

    A typical way to do this is using alternation in RE. You can dynamically generate the RE...

    my @REs = qw( this that \w\d\w ); my $re = join '|', @REs; # join with | for alternation $re = qr/($re)/; # compile for efficiency print "Matched $1\n" if $str =~ m/$re/;

    cheers

    tachyon

Re: RegEx Array
by graff (Chancellor) on Apr 12, 2004 at 06:00 UTC
    I suppose you've just given us a "toy" example that doesn't really reflect the complexity of your task. But just in case your task really does look like that, you could avoid the use of an array of regexes by simply allowing more leeway in a single regex:
    if ( $string =~ /(Field\d):\s+(\w{3})/ ) { print "matched on $1: $2\n"; }
Re: RegEx Array
by pbeckingham (Parson) on Apr 12, 2004 at 14:47 UTC

    I assume your example contains generic field names, but you could use:

    my $string = 'Field1: one'; print "$1\n" if $string =~ /(?:Field1:|Field2:|Field3:)\s+(\w{3})/;
    Or if those really are your field names:
    my $string = 'Field1: one'; print "$1\n" if $string =~ /Field\d:\s+(\w{3})/;
    The point being that if the set of regexes is small and static, combine them for simpler code (first example), or for better performance (second example).