Как использовать интеллектуальное сопоставление Perl для одновременного сопоставления множества шаблонов? - PullRequest
2 голосов
/ 16 сентября 2010

Я пытался следовать некоторым примерам, чтобы использовать интеллектуальное сопоставление в следующем фрагменте кода, но не получилось (ничего не было отфильтровано). Как я могу использовать интеллектуальное сопоставление здесь для сопоставления с несколькими регулярными выражениями одновременно?

my $regexes_to_filter_a = ("tmp", "temp", "del")
my @organism_dirs = (); # this will hold final list of dirs to processs

my @subdirs = File::Find::Rule->directory->maxdepth(1)->in($root_dir);
foreach my $subdir (@subdirs) {
    my $filter = 0;

    # IMPROVE: can do smart matching here
    foreach my $regex ( @{$regexes_to_filter_a} ) {
        if ( basename($subdir) =~ $regex ) {
            $filter = 1; # filter out this dir
            last;
        }
    }

    unless ($filter) {
        push @organism_dirs, $subdir;
    }
}

Ответы [ 2 ]

3 голосов
/ 16 сентября 2010

Вам не нужно умное сопоставление здесь. ~~ с одним регулярным выражением в правой части и строкой в ​​левой части также может быть = ~, как и у вас. Что ты пытаешься сделать?

Для вашего матча у вас есть два пути. Если вы хотите использовать строку в качестве шаблона, вам нужно использовать оператор соответствия:

 basename($subdir) =~ m/$regex/

Если вы не хотите использовать оператор сопоставления, как сейчас, вам нужен объект регулярного выражения:

 my $regexes_to_filter_a = (qr/tmp/, qr/temp/, qr/del/);

Полагаю, вы могли бы сопоставить все регулярные выражения одновременно. Обратите внимание, что если вы собираетесь установить maxdepth на 1, вам не нужен File :: Find :: Rule. Если вы не собираетесь обходить структуру каталогов, не используйте модуль, предназначенный для обхода структуры каталогов:

my $regexes_to_filter_a = (qr/tmp/, qr/temp/, qr/del/);
my @organism_dirs = ();

foreach my $subdir ( glob( '*' ) ) {
    next unless -d $subdir;
    unless (basename($subdir) ~~ @regexes_to_filter_a) {
        push @organism_dirs, $subdir;
            } 
        }

Я думаю, что все это слишком много работы, хотя. Если вы хотите исключить известные статические имена каталогов (а не шаблоны), просто используйте хеш:

my %ignore = map { $_, 1 } qw( tmp temp del );

my @organism_dirs = 
    grep { ! exists $ignore{ basename($_) } } 
    glob( "$rootdir/*" );

Если вы действительно хотите использовать умный матч:

my %ignore = map { $_, 1 } qw( tmp temp del );

my @organism_dirs = 
    grep { basename($_) ~~ %ignore } 
    glob( "$rootdir/*" );
2 голосов
/ 16 сентября 2010

Вот быстрое непроверенное изменение вашего примера:

my @regexes_to_filter_a = (qr/^tmp$/, qr/^temp/, qr/del/);
my @organism_dirs = (); # this will hold final list of dirs to processs

my @subdirs = File::Find::Rule->directory->maxdepth(1)->in($root_dir);
foreach my $subdir (@subdirs) {

    unless (basename($subdir) ~~ @regexes_to_filter_a) {
        push @organism_dirs, $subdir;
    }
}

Ключевые изменения:

i) должно быть @array = (...list...); или $array_ref = [...list...];

my @regexes_to_filter_a = ("tmp", "temp", "del");

ii) и перейдите на использование smart match .Ниже проверяется, что basename($subdir) находится в (~~) массиве @regexes_to_filter_a.Поэтому нет необходимости циклически проходить по массиву и выполнять отдельные проверки регулярных выражений.

unless (basename($subdir) ~~ @regexes_to_filter_a) { ... }

/ I3az /

...