Search code examples
regexperlsmartmatch

How do I use Perl's smart matching to match many patterns at once?


I was trying to follow some examples to use smart matching in the following piece of code, but failed (nothing was filtered out). How can I use smart matching here to match against multiple regexes at once?

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

Solution

  • Here is a quick untested change to your example:

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

    The key changes are:

    i) should be either @array = (...list...); or $array_ref = [...list...];

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

    ii) and change to using smart match. Below checks that basename($subdir) is in (~~) the @regexes_to_filter_a array. So no need to loop through the array and do individual regex checks.

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

    /I3az/