如何使用Perl的智能匹配同时匹配多种模式?

时间:2010-09-16 06:46:08

标签: regex perl smartmatch

我试图按照一些示例在下面的代码中使用智能匹配,但是失败了(没有过滤掉)。如何在此处使用智能匹配来同时匹配多个正则表达式?

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 个答案:

答案 0 :(得分:3)

这里不需要智能匹配。右边有一个正则表达式,左边有一个字符串的~~也可能是a =〜,就像你拥有它一样。你想做什么?

对于你的比赛,你有两种方法可以选择。如果要将字符串用作模式,则需要使用匹配运算符:

 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/*" );

答案 1 :(得分:2)

以下是对您的示例的快速未经测试的更改:

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 /