Claude
Claude

Reputation: 171

Perl: display regexp, not match

I have this sample code

#!/usr/bin/perl
use strict;
use warnings;
my $string = "Dear Brother,fgfgfg Test Test2 Soon trthggh";

if ($string =~ /(expr1|expr2|dear.{0,6}(brother|friend)|Soon)/i){print "$1";}

$1 will display the match which is "Dear Brother". Is there a way to get the full regepx who match this string?

In this case

dear.{0,6}(brother|friend)

It is possible to do that?

Upvotes: 2

Views: 132

Answers (3)

jiandingzhe
jiandingzhe

Reputation: 2121

Maybe you could use this approach:

my $part2 = "(brother|friend)";
my $part1 = "(expr1|expr2|dear.{0,6}$part2|Soon)";

my $string = "Dear Brother,fgfgfg Test Test2 Soon trthggh";
if ($string =~ /$part1/i){print "$part1";}

I don't know any more automated way. Maybe you have to hack into a regex engine, not using Perl directly.

Upvotes: -1

Corion
Corion

Reputation: 3925

If you are creating the regex using a program anyway, it's easy to inject the appropriate (?<...>) sequences and then just look which one(s) matched afterwards. Adapting the program you posted as first attempt:

#!/usr/bin/perl
use strict;
use warnings;

my $string = "Dear Brother, fgfgfg Test Test2 Soon trthggh";
my @regexarray = (qr/expr1/, qr/expr2/, qr/dear.{0,6}(brother|friend)/i, qr/Soon/, qr/out.php\?s=(7644|4206|6571|4205)/);
my $i= 0;

my $regexstring = join "|", map {
    my $groupname= sprintf 'group_%d', $i++;
    qr/(?<$groupname>$_)/i
} @regexarray;

if ($string =~ /($regexstring)/i){
    my $match = $1; 
    print "Found <$1>\n";
    print "Matched via ";
    (my $found) = keys %+;
    print "$found => $+{$found}\n" for keys %+;
    $found =~ /(\d+)$/
        or die "Invalid group name '$found'";
    my $index = $1;
    print "Matched via /$regexarray[ $index ]/\n";
}

I've switched the strings to regular expressions above to make quoting and case-insensitivity easier.

Output

Found <Dear Brother>
Matched via group_2 => Dear Brother
Matched via /(?^i:dear.{0,6}(brother|friend))/

Upvotes: 5

Claude
Claude

Reputation: 171

I have this working solution. But on too many expressions, I think the loop may slow down the script. Other, better ideas are welcome, but please stop telling me about $1 or $&.

#!/usr/bin/perl
use strict;
use warnings;


my $string = "Dear Brother, fgfgfg Test Test2 Soon trthggh";
my $regexstring = "expr1|expr2|dear.{0,6}(brother|friend)|Soon|out.php\?s=(7644|4206|6571|4205)";
my @regexarray = ("expr1", "expr2", "dear.{0,6}(brother|friend)", "Soon", "out.php\?s=(7644|4206|6571|4205)");

if ($string =~ /($regexstring)/i){
    my $match = $1; 
    for my $expr (@regexarray){
        print "$expr\n" if ($match =~ /($expr)/i);
    }
}

Upvotes: 2

Related Questions