Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Matching Multiple Patters In A Regex In Any Order

Reply
Thread Tools

Matching Multiple Patters In A Regex In Any Order

 
 
Hal Vaughan
Guest
Posts: n/a
 
      09-26-2005
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
 
Reply With Quote
 
 
 
 
jl_post@hotmail.com
Guest
Posts: n/a
 
      09-26-2005
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

 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      09-27-2005
<> 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.
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      09-28-2005
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....e769be57f07393

[2] http://faq.perl.org/perlfaq6.html#How_do_I_efficiently


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Regex testing and UTF8 awarenes or Regex and numeric pattern matching sln@netherlands.com Perl Misc 2 03-10-2009 03:51 AM
Help with Pattern matching. Matching multiple lines from while reading from a file. Bobby Chamness Perl Misc 2 05-03-2007 06:02 PM
String Pattern Matching: regex and Python regex documentation Xah Lee Python 8 09-26-2006 03:24 PM
String Pattern Matching: regex and Python regex documentation Xah Lee Perl Misc 2 09-25-2006 03:15 AM
String Pattern Matching: regex and Python regex documentation Xah Lee Java 1 09-22-2006 07:11 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57