I am working on a project which at one point gets a list of files from an ftp server. At that point it either returns an arrayref of files OR if an optional regex reference
See nparen in Regexp::Parser.
use strictures;
use Carp qw(carp);
use Regexp::Parser qw();
my $parser = Regexp::Parser->new;
sub filter_files {
my ($files, $pattern) = @_;
my @files = @$files;
return \@files unless $pattern;
carp sprintf('Could not inspect regex "%s": %s (%d)',
$pattern, $parser->errmsg, $parser->errnum)
unless $parser->regex($pattern);
my %versions;
@files = map {
if (my ($capture) = $_ =~ $pattern) {
$parser->nparen
? push @{ $versions{$capture} }, $_
: $_
} else {
()
}
} @files;
carp 'Could not find any matching files' unless @files;
return (scalar keys %versions)
? \%versions
: \@files;
}
Another possibility to avoid inspecting the pattern is to simply rely on the value of $capture
. It will be 1
(Perl true value) in the case of a successful match without capture. You can distinguish it from the occasional capture returning 1
because that one lack the IV
flag.
You could use something like:
sub capturing_groups{
my $re = shift;
"" =~ /|$re/;
return $#+;
}
say capturing_groups qr/fo(.)b(..)/;
Output:
2
You could use YAPE::Regex to parse the regular expression to see if there is a capture present:
use warnings;
use strict;
use YAPE::Regex;
filter_files(qr/foo.*/);
filter_files(qr/(foo).*/);
sub filter_files {
my ($pattern) = @_;
print "$pattern ";
if (has_capture($pattern)) {
print "yes capture\n";
}
else {
print "no capture\n";
}
}
sub has_capture {
my ($pattern) = @_;
my $cap = 0;
my $p = YAPE::Regex->new($pattern);
while ($p->next()) {
if (scalar @{ $p->{CAPTURE} }) {
$cap = 1;
last;
}
}
return $cap;
}
__END__
(?-xism:foo.*) no capture
(?-xism:(foo).*) yes capture