I am not completely sure what you want to do here, but I don't think your program does what you think it does.
You are useing eval
with a BLOCK of code. That's like a try
block. If it die
s inside of that eval
block, it will catch that error. It will not run your string like it was code. You need a string eval
for that.
Instead of explaining that, here's an alternative.
This program uses sprintf
and numbers the parameters. The %1$s
syntax in the pattern says _take the first argument (1$
) and format it as a string (%s
). You don't need to localize or assign to $_
to do a match. The =~
operator does that on other variables for you. I also use qr{}
to create a quoted regular expression (essentially a variable containing a precompiled pattern) that I can use directly. Because of the {}
as delimiter, I don't need to escape the slashes.
use strict;
use warnings;
use feature 'say'; # like print ..., "\n"
my %testHash = (
qr{(\d+)/(\d+)/(\d+)} => '%1$s.%2$s.%3$s',
qr{(\d+)/(\d+)/(\d+) nomatch} => '%1$s.%2$s.%3$s',
qr{(\d+)/(\d+)/(\d\d\d\d)} => '%3$4d-%2$02d-%1$02d',
qr{\d} => '%s', # no capture group
);
my $str = '1/12/2016';
foreach my $pattern ( keys %testHash ) {
my @captures = ( $str =~ $pattern );
say "pattern: $pattern";
if ($#+ == 0) {
say " no capture groups";
next;
}
unless (@captures) {
say " no match";
next;
}
# debug-output
for my $i ( 1 .. $#- ) {
say sprintf " \$%d - %s", $i, $captures[ $i - 1 ];
}
say sprintf $testHash{$pattern}, @captures;
}
I included four examples:
- The first pattern is the one you had. It uses
%1$s
and so on as explained above.
- The second one does not match. We check the number of elements in
@captured
by looking at it in scalar context.
- The third one shows that you can also reorder the result, or even use the
sprintf
formatting.
- The last one has no capture group. We check by looking at the index of the last element (
$#
as the sigil for arrays that usually have an @
sigil) in @+
, which holds the offsets of the ends of the last successful submatches in the currently active dynamic scope. The first element is the end of the overall match, so if this only has one element, we don't have capture groups.
The output for me is this:
pattern: (?^:(\d+)/(\d+)/(\d\d\d\d))
$1 - 1
$2 - 12
$3 - 2016
2016-12-01
pattern: (?^:(\d+)/(\d+)/(\d+) nomatch)
no match
pattern: (?^:\d)
no capture groups
pattern: (?^:(\d+)/(\d+)/(\d+))
$1 - 1
$2 - 12
$3 - 2016
1.12.2016
Note that the order in the output is mixed up. That's because hashes are not ordered in Perl, and if you iterate over the keys in a hash without sort
the order is random.