Matching Multiple Patters In A Regex In Any Order

Discussion in 'Perl Misc' started by Hal Vaughan, Sep 26, 2005.

  1. Hal Vaughan

    Hal Vaughan Guest

    I've been reading the FAQ on Regexes and I see I can map to create an array
    of patterns to be found in a Regex, like this:

    @patterns = map { qr/\b$_\b/i } qw( foo bar baz );

    LINE: while( <> ) {
    foreach $pattern ( @patterns ) {
    print if /\b$pattern\b/i;
    next LINE;
    }
    }

    And the next example talks about backtracking, as well.

    I think I remember, at some point, reading how it was possible to specify an
    array or hash in a regex to see if one or more of multiple matches were
    found, someting like:

    @pattern = qw(foo bar baz);
    if ($line =~ /@pattern/) {print "Found a match!\n";}

    I KNOW that does not work, as is, but I've been trying to find out if there
    was something similar using an array or hash to check multiple values. I
    thought I remembered also being able to do something like:

    @pattern = qw(fooba? f.*?bar);
    (@found) = $line =~ /@pattern/);

    Which would find all the matches for both regexes specified in @pattern and
    put them all in @found.

    Is this possible? Is there some way, other than interating through a loop,
    to match multiple patterns?

    Thanks!

    Hal
     
    Hal Vaughan, Sep 26, 2005
    #1
    1. Advertising

  2. Hal Vaughan

    Guest

    Hal Vaughan wrote:
    > I've been reading the FAQ on Regexes and I see
    > I can map to create an array of patterns to be
    > found in a Regex, like this:
    >
    > @patterns = map { qr/\b$_\b/i } qw( foo bar baz );
    >
    > LINE: while( <> ) {
    > foreach $pattern ( @patterns ) {
    > print if /\b$pattern\b/i;
    > next LINE;
    > }
    > }
    >
    > I think I remember, at some point, reading how it
    > was possible to specify an array or hash in a regex
    > to see if one or more of multiple matches were
    > found, someting like:
    >
    > @pattern = qw(foo bar baz);
    > if ($line =~ /@pattern/) {print "Found a match!\n";}



    Try this instead:

    my $pattern = join '|', qw(foo bar baz);
    if ($line =~ /\b($pattern)\b/) {print "Found a match!\n";}


    > I've been trying to find out if there was something
    > similar using an array or hash to check multiple values.
    > I thought I remembered also being able to do something like:
    >
    > @pattern = qw(fooba? f.*?bar);
    > (@found) = $line =~ /@pattern/);
    >
    > Which would find all the matches for both regexes specified in @pattern and
    > put them all in @found.
    >
    > Is this possible? Is there some way, other than interating through a loop,
    > to match multiple patterns?



    Yes, it's possible. Try this:

    my $line = "baz baz foo";
    my $pattern = join '|', qw(foo bar baz);
    my @found = ($line =~ m/\b($pattern)\b/g);

    Just remember to put in the "/g" modifier. Otherwise, only the first
    match will be placed in the @found array.

    I hope this helps, Hal.

    -- Jean-Luc
     
    , Sep 26, 2005
    #2
    1. Advertising

  3. Hal Vaughan

    Anno Siegel Guest

    <> wrote in comp.lang.perl.misc:
    > Hal Vaughan wrote:
    > > I've been reading the FAQ on Regexes and I see
    > > I can map to create an array of patterns to be
    > > found in a Regex, like this:
    > >
    > > @patterns = map { qr/\b$_\b/i } qw( foo bar baz );
    > >
    > > LINE: while( <> ) {
    > > foreach $pattern ( @patterns ) {
    > > print if /\b$pattern\b/i;
    > > next LINE;
    > > }
    > > }
    > >
    > > I think I remember, at some point, reading how it
    > > was possible to specify an array or hash in a regex
    > > to see if one or more of multiple matches were
    > > found, someting like:
    > >
    > > @pattern = qw(foo bar baz);
    > > if ($line =~ /@pattern/) {print "Found a match!\n";}

    >
    >
    > Try this instead:
    >
    > my $pattern = join '|', qw(foo bar baz);
    > if ($line =~ /\b($pattern)\b/) {print "Found a match!\n";}


    This is probably what the OP was up to, but it has some problems.
    The test patterns should be mapped through quotemeta() in case the
    strings contain regex metacharacters. Also, the parentheses around
    $pattern should be non-capturing.

    my $pattern = join '|', map quotemeta, qw( foo bar baz);
    if ( $line =~ /\b(?:$pattern)\b/ ) { # etc.

    It doesn't matter in this case, but if you care which string matched
    it is often useful to sort the test strings into descending order
    by length. If one string is a substring of another, that guarantees
    that the bigger string is tried first.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Sep 27, 2005
    #3
  4. Hal Vaughan wrote:

    > Is this possible? Is there some way, other than interating through a loop,
    > to match multiple patterns?


    Yes, but it's generally less efficient[1]. This is why the FAQ[2]
    advises a loop. Recent versions do at least show the other way for
    completeness.


    [1] Benchmark in previous thread "Regex combining /(foo|bar)/ slower
    than using foreach (/foo/,/bar/)?"
    http://groups.google.com/group/comp..._frm/thread/e6511d1fee90f808/cfe769be57f07393

    [2] http://faq.perl.org/perlfaq6.html#How_do_I_efficiently
     
    Brian McCauley, Sep 28, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Xah Lee
    Replies:
    1
    Views:
    971
    Ilias Lazaridis
    Sep 22, 2006
  2. Xah Lee
    Replies:
    8
    Views:
    482
    Ilias Lazaridis
    Sep 26, 2006
  3. Xah Lee
    Replies:
    2
    Views:
    239
    Xah Lee
    Sep 25, 2006
  4. Bobby Chamness
    Replies:
    2
    Views:
    263
    Xicheng Jia
    May 3, 2007
  5. Replies:
    2
    Views:
    416
Loading...

Share This Page