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

Hello fellow monks,

I've got this apparently silly question, to which I didn't find any info anywhere.

Basically I've got this regex:

my $regex = qr/foo\d+|bar\S+?/;

So when I want to match it on a string:

$_ =~ m/($regex)/;

how can I get returned in the $1 the pattern instead of the matched part of the string??

Thanks for any kind help you will give me!

Replies are listed 'Best First'.
Re: Regex: return the pattern instead of the actual match
by ww (Archbishop) on Sep 15, 2011 at 12:26 UTC
    In view of the alternation, perhaps OP means that the intent is to print that part of the regex that produced the match.

    That could be achived by using multiple regexen instead of alternation:

    #!/usr/bin/perl use strict; use warnings; use 5.012; # #926110 my $regex1 = qr/foo\d+/; my $regex2 = qr/bar\S+?/; my @string = qw(foo17 barABC nomatch); for my $string(@string) { if ($string =~ m/($regex1)/ && $regex1 =~ /(.*)/s) { say "$1 when string is \"$string\""; } elsif ( $string=($regex2) && $regex2 =~ /(.*)/s ) { say "$1 when string is \"$string\""; } else { say "no match on $string"; } }
    which produces this:
    (?-xism:foo\d+) when string is "foo17" (?-xism:bar\S+?) when string is "barABC" (?-xism:bar\S+?) when string is "nomatch"

    Update: Or, better (simpler and more info in output):

    hashbang, strict, warn, etc... my $regex1 = qr/foo\d+/; my $regex2 = qr/bar\S+?/; my @string = qw(foo17 barABC this-has-no-match); for my $string(@string) { if ($string =~ m/($regex1)/) { say "matched part of \"$string\" is $1 when regex is \"$r +egex1\""; next; } elsif ( $string=~ m/($regex2)/ ) { say "matched part of \"$string\" is $1 when regex is \"$regex2 +\""; next; } else { say "no match on $string"; } }
    outputting:
    matched part of "foo17" is foo17 when regex is "(?-xism:foo\d+)" matched part of "barABC" is barA when regex is "(?-xism:bar\S+?)" no match on this-has-no-match
Re: Regex: return the pattern instead of the actual match
by Corion (Patriarch) on Sep 15, 2011 at 10:47 UTC

    You can't, and it doesn't make much sense to do so. Maybe you want something like this:

    my $matched_pattern; if (/$regex/) { $matched_pattern = $regex; };

    If you're really bent on filling $1 with an arbitrary string, you can do so by doing:

    my $regex = qr/foo/; $regex =~ /^(.+)$/ms; # fill $1 with $regex print $1;

    This does not make sense to me, so most likely I misunderstood your question. If you want something else, please tell us the output you want.

Re: Regex: return the pattern instead of the actual match
by rovf (Priest) on Sep 15, 2011 at 11:14 UTC
    I don't know why you want to do this, but if you store the Regexp as a string, you allready have the pattern:

    my $regex = 'foo\\d+|bar\S+?'; ... m/($regex)/;
    Now, matched part of the $_ is in $1 and the pattern corresponding to this, is in $regex.

    -- 
    Ronald Fischer <ynnor@mm.st>
Re: Regex: return the pattern instead of the actual match
by moritz (Cardinal) on Sep 15, 2011 at 11:26 UTC
Re: Regex: return the pattern instead of the actual match
by JavaFan (Canon) on Sep 15, 2011 at 11:50 UTC
    So you want $1 eq $regex? You cannot directly assign to $1, but try this:
    if ($_ =~ m/($regex)/ && $regex =~ /(.*)/s) { ... Now $1 will contain $regex ... }
    I just cannot figure out why you want this.
Re: Regex: return the pattern instead of the actual match
by johngg (Canon) on Sep 15, 2011 at 12:47 UTC

    Perhaps you are trying to see which of the two alternations matched. I wonder if this would be close enough.

    $ perl -E ' > $rx = qr{(?x) > ( > foo\d+(?{say q{matched foo\d+}}) > | > bar\S+?(?{say qq{matched bar\S+?}}) > ) > }; > q{abcfoo44fred} =~ $rx && say qq{captured $1}; > q{barbell} =~ $rx && say qq{captured $1}; > q{xyz} =~ $rx && say qq{captured $1};' matched foo\d+ captured foo44 matched bar\S+? captured barb $

    I hope this is helpful.

    Cheers,

    JohnGG

      Hi John

      That's exactly what I needed!! Thanks a lot for your help!!

Re: Regex: return the pattern instead of the actual match
by ikegami (Patriarch) on Sep 15, 2011 at 14:43 UTC
    my $matching_pattern = /$pattern/ && $pattern;
Re: Regex: return the pattern instead of the actual match
by Anonymous Monk on Sep 15, 2011 at 20:55 UTC

    This only works if there are no capturing parenthesis:

    #!/usr/bin/perl use v5.12; use warnings; use strict; my @alt = ( qr/foo\d+/, qr/bar\S+?/, ); my $re = join '|', map qr/($_)/, @alt; for my $word (qw[foofoo2010 subarashii bowwowmeow]) { my $_ = $word; if (s/$re/($+)/) { say "$word => $_: $alt[$#- - 1]"; } else { say "$word: NO_MATCH"; } }

    This is the output:

    foofoo2010 => foo(foo2010): (?-xism:foo\d+) subarashii => su(bara)shii: (?-xism:bar\S+?) bowwowmeow: NO_MATCH
Re: Regex: return the pattern instead of the actual match
by LanX (Saint) on Sep 16, 2011 at 09:03 UTC
    As a proof of concept for this advice for perl versions >=5.10.
    use strict; use warnings; $\="\n"; my %sp= ( foo => 'foo\d+', bar => 'bar\S+?' ); my $regex='§foo§|§bar§'; # template $regex=~s/§(\w+)§/(?<$1>$sp{$1})/g; #print $regex; my $str=" foo15 "; if ($str =~ m/$regex/) { while ( my( $name, $pos) = each %+ ) { print "$sp{$name} matched" if $pos; } }

    Cheers Rolf

Re: Regex: return the pattern instead of the actual match
by Anonymous Monk on Sep 15, 2011 at 10:44 UTC
    Wrap the parts of your regex definition into named capture groups, then inspect the %+ hash after matching. The info is in perlre.
      Rubbish. The keys of %+ gives you the names of the capture group, the values give you the part of the string that's matched. It doesn't give you the (sub)pattern.
        Re-Rubbish! It's a very good advice.

        Associating the name of the capture group to the subpattern solves the problem.

        Cheers Rolf

      Hi,

      sadly, I have no access to a more recent perl version than the 5.8.8, so I can't use no named grouping within regex's. Thanks though for the advice!