Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: Finding out which of a list of patterns matched

by nobull (Friar)
on Jan 22, 2006 at 11:06 UTC ( #524769=note: print w/replies, xml ) Need Help??

in reply to Finding out which of a list of patterns matched

$#- gives the number of the last capture in the last regex that was successful. With simple alternation as in this case you can just make each alternative a caputure.
if ( /(foo)|(bar)|(baz)/ ) { print "$#-\n"; }
For details, see the description of @- in perlvar.

Replies are listed 'Best First'.
Re^2: Finding out which of a list of patterns matched
by tirwhan (Abbot) on Jan 22, 2006 at 11:35 UTC

    In your example, $#- will always be 1, because the conditional is fulfilled after the first match. Also, $#- can't really be useful in this matter at all, because it returns the index of the last match in @- ,which in turn gives you the match offset into the string, not the matched content.

    Update: This is completely wrong and nobull is correct, my apologies (hangs head in shame). To make up for it, here's a practical example of finding your matched word with nobull's method (I still like my method below better, but YMMV):

    my @words = qw(foo bar baz); my $regex = join(")|(",grep { quotemeta($_) } @words); if ($input =~ m/($regex)/ ){ my $index = $#- -1; print "matched word $words[$index]\n"; }

    There are ten types of people: those that understand binary and those that don't.
      I still like my method below better <snip>

      I don't. The OP specifically states "I'll potentially have quite a lot of patterns to test". What if "quite a lot" means, say, 50, or 500, or 5,000? Your dispatch table could become unmanageably long...

        By "my method" I meant using capturing parentheses and $1 to retrieve the match, instead of $#-. The dispatch table is just the next step and not tied to the method of finding the value to act on.

        But regardless of that, what's the problem with a long dispatch table? You don't actually need to store the actions as anonymous subs of course, if you have several values which correspond to the same action you just use references to subs which you define elsewhere. This is certainly more manageable than endless if-elsif blocks. Sure, it's no silver bullet (e.g. if you only have three actions which each map to 1000 possible keywords you probably wouldn't go that way), but without knowing more about the OPs requirements it's impossible to tell how appropriate the solution is.

        Maybe I'm not understanding your objection correctly though, would you care to give a solution that's more manageable for 5000 values?

        Update: here's an example of how you could set up a dispatch table with lots of values matching to less (and potentially longer) subroutines:

        my @v1=qw(horse hearse house hose); my @v2=qw(fax fix fox flux); my @v3=qw(orange lemon melon plum apple banana rama); my $regex = join("|",@v1,@v2,@v3); sub one { print "Begins with an h\n"; } sub two { print "Oh those Xes\n"; } sub three { print "Yummy!\n"; } my %table; @table{@v1,@v2,@v3}=((\&one)x scalar(@v1), (\&two)x scalar(@v2), (\&three)x scalar(@v3)); if (my ($match) = $input =~ m/($regex)/) { &{$table{$match}}; }

        Seems manageable to me, even if you imagine this expands by a considerable amount.

        There are ten types of people: those that understand binary and those that don't.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://524769]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2023-06-01 09:32 GMT
Find Nodes?
    Voting Booth?

    No recent polls found