Matching Multiple Patters In A Regex In Any Order

H

Hal Vaughan

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
 
J

jl_post

Hal said:
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
 
A

Anno Siegel

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
 
B

Brian McCauley

Hal said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top