2011-12-28 39 views
10

Tôi đang làm việc trên một dự án mà tại một thời điểm nhận được một danh sách các tập tin từ một máy chủ FTP. Tại thời điểm đó, nó trả về một mảng của các tệp HOẶC nếu tham chiếu regex tùy chọn (tức là qr), được thông qua, nó lọc danh sách xuống bằng grep. Hơn nữa, nếu qr có nhóm chụp, nó xử lý phần được chụp dưới dạng số phiên bản và trả về thay vì hashref trong đó khóa là phiên bản và giá trị là tên tệp (sẽ được trả về làm mảng nếu không có nhóm chụp) . Mã trông giống như (đơn giản hóa một chút)Đếm các nhóm chụp trong regex qr?

sub filter_files { 
    my ($files, $pattern) = @_; 
    my @files = @$files; 
    unless ($pattern) { 
    return \@files; 
    } 

    @files = grep { $_ =~ $pattern } @files; 
    carp "Could not find any matching files" unless @files; 

    my %versions = 
    map { 
     if ($_ =~ $pattern and defined $1) { 
     ($1 => $_) 
     } else { 
     () 
     } 
    } 
    @files; 

    if (scalar keys %versions) { 
    return \%versions; 
    } else { 
    return \@files; 
    } 
} 

Triển khai này cố gắng tạo băm và trả về nếu thành công. Câu hỏi của tôi, là tôi có thể phát hiện rằng qr có một nhóm chụp và chỉ cố gắng để tạo ra các hash nếu nó?

Trả lời

18

Bạn có thể sử dụng một cái gì đó như:

sub capturing_groups{ 
    my $re = shift; 
    "" =~ /|$re/; 
    return $#+; 
} 

say capturing_groups qr/fo(.)b(..)/; 

Output:

2 
+2

cho tôi biết nếu tôi nhận được nó: bạn khớp một chuỗi rỗng với sự thay đổi không có gì hoặc regex của tôi. Không có gì cho phép nó phù hợp, nhưng nó vẫn populates @ +, mà sau đó có số lượng các nhóm nắm bắt như số lượng các yếu tố. Tôi có đúng không? Rất thông minh! –

+2

(sửa) ... sau đó có thêm một phần tử so với ảnh chụp (vì $ + [0] là đối sánh) nhưng vì $ # + nhỏ hơn số phần tử, nó trả về số kết quả phù hợp –

+0

@JoelBerger , chính xác. :-) – Qtax

3

Bạn có thể sử dụng YAPE::Regex để phân tích các biểu thức chính quy để xem nếu có là một ảnh chụp hiện tại:

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 
+2

Đây là những gì tôi mong đợi, nhưng Qtax của có vẻ đơn giản hơn nhiều và có ít deps. Cảm ơn mặc dù. –

4

Xem 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; 
} 

Một khả năng khác để tránh kiểm tra mẫu đơn giản là dựa vào giá trị $capture. Nó sẽ là 1 (giá trị thực đúng của Perl) trong trường hợp khớp thành công mà không cần chụp. Bạn có thể phân biệt nó với ảnh chụp không thường xuyên quay trở lại 1 vì ảnh đó thiếu cờ IV.

+1

giống như công cụ, cảm ơn vì đã thực hiện công việc khó khăn này, nhưng tôi nghĩ tôi sẽ chấp nhận câu trả lời của Qtax. Dường như với tôi mà dựa vào việc thực hiện riêng của Perl của động cơ regex có vẻ dễ dàng hơn là phân tích cú pháp. Cảm ơn mặc dù! Tôi thực sự mong rằng câu trả lời sẽ kết thúc như thế này. –

Các vấn đề liên quan