Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

capture value from two patterns

by vitoco (Hermit)
on Aug 20, 2020 at 19:50 UTC ( [id://11120938]=perlquestion: print w/replies, xml ) Need Help??

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

Hi!

I usually capture and assign a variable this way:

my ($id) = (m!/key/(\d+)!);

I need to add another pattern for the same capture because sometimes the string changes:

my ($id) = (m!/(\d+)-\d+!);

How could I combine both patterns to get only one capture for both possible sources? Obvously this does not work as it gets 2 captures:

my ($id) = (m!/key/(\d+)|/(\d+)-\d+!);

A workaround could be the following:

my $id = $1 // $2 if m!/key/(\d+)|/(\d+)-\d+!;

I want to know I there is a way to get only one capture from two different surrounding strings in a single pattern.

Thanks!

Replies are listed 'Best First'.
Re: capture value from two patterns
by jo37 (Deacon) on Aug 20, 2020 at 20:20 UTC

    You may use the "branch reset" pattern:

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; for (qw(/key/123 /123-456)) { my ($id) = m!(?|/key/(\d+)|/(\d+)-\d+)!; say $id; } __DATA__ 123 123

    EDIT: Added the missing leading slash in the second branch.

    Greetings,
    -jo

    $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

      The branch reset operator is a regex pattern extension added with Perl version 5.10. For those of you still clomping around in the pre-5.10 Stone Age, here's an old-school alternative:

      c:\@Work\Perl\monks>perl -wMstrict -le "for my $s (qw(/key/42 /key/ /24-99 /24- /24 /key/42-99)) { my $parsed = my ($id) = grep defined, $s =~ m{ \A (?: /key/ (\d+) | / (\d+) - \d+) \z }xms; ;; print qq{'$s' -> }, $parsed ? qq{'$id'} : 'no id'; } " '/key/42' -> '42' '/key/' -> no id '/24-99' -> '24' '/24-' -> no id '/24' -> no id '/key/42-99' -> no id
      (Of course, this still works post-5.10!)


      Give a man a fish:  <%-{-{-{-<

      You may use the "branch reset" pattern:

      Thanks! It works exactly as I wanted to...

Re: capture value from two patterns
by Haarg (Priest) on Aug 21, 2020 at 07:42 UTC
    my ($id) = grep defined, (m!/key/(\d+)|/(\d+)-\d+!);
Re: capture value from two patterns
by LanX (Saint) on Aug 20, 2020 at 20:42 UTC
    TIMTOWTDI

    that's IMHO the shortest and most intuitive

    DB<35> $_='a' DB<36> ; /(a)/ or /(b)/; $x= $1 DB<37> p $x a DB<38> $_='b' DB<39> ; /(a)/ or /(b)/; $x= $1 DB<40> p $x b DB<41>

    I'm aware you wanted the list assignment approach, but it's longer because you'd need to repeat ($x) = for each term and I prefer DRY idioms.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      It's also ambiguous if all matches fail:

      c:\@Work\Perl\monks>perl -wMstrict -le "for (qw(a X b)) { /(a)/ or /(b)/; my $id = $1; print qq{'$_' -> '$id'}; } " 'a' -> 'a' 'X' -> 'a' 'b' -> 'b'

      Update 1: Something like
          my $id = $1 // $2 if m!/key/(\d+)|/(\d+)-\d+!;
      (if you avoid the problem of the conditionally declared lexical!) does not suffer this:

      c:\@Work\Perl\monks>perl -wMstrict -le "for (qw(a X b)) { /(a)|(b)/ or next; my $id = $1 // $2; print qq{'$_' -> '$id'}; } " 'a' -> 'a' 'b' -> 'b'

      Update 2: Slight wording change to first sentence.


      Give a man a fish:  <%-{-{-{-<

        good point, $1 sticks to the last successful match

        so always check before accessing it

        for (qw(a X b)) { my $id = $1 if /(a)/ or /(b)/; print qq{'$_' -> '$id'\n}; }

        C:/Perl_524/bin\perl.exe -w d:/exp/pm_or_regex.pl Use of uninitialized value $id in concatenation (.) or string at d:/ex +p/pm_or_regex.pl line 5. 'a' -> 'a' 'X' -> '' 'b' -> 'b'

        I kept the warning in intentionally.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11120938]
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2024-03-28 09:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found