Count the capture groups in a qr regex?

后端 未结 3 663
庸人自扰
庸人自扰 2021-01-04 13:40

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

相关标签:
3条回答
  • 2021-01-04 14:25

    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.

    0 讨论(0)
  • 2021-01-04 14:34

    You could use something like:

    sub capturing_groups{
        my $re = shift;
        "" =~ /|$re/;
        return $#+;
    }
    
    say capturing_groups qr/fo(.)b(..)/;
    

    Output:

    2
    
    0 讨论(0)
  • 2021-01-04 14:41

    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
    
    0 讨论(0)
提交回复
热议问题