在Perl中使用regex有效匹配一组文件名

时间:2013-06-10 17:41:18

标签: regex perl

我正在使用Perl捕获某些指定文件夹中的文件名,这些文件夹中包含某些单词。这些文件名中的关键字是“offer”或“已清除”和“regup”或“regdn”。换句话说,“offer”或“clear”之一和“regup”或“regdn”之一必须在文件名中出现为正匹配。这两个单词可以是任何顺序,并且在它们前面和后面会出现字符/单词。匹配文件名的示例是:

2day_Agg_AS_Offers_REGDN-09-JUN-11.csv

我有一个正则表达式,成功地将每个匹配的文件名作为完整路径捕获,这是我想要的,但它似乎不优雅和低效。尝试稍好的代码都失败了。

工作方法:

# Get the folder names
my @folders = grep /^\d{2}-/, readdir DIR;

foreach my $folder ( @folders ) {
    # glob the contents of the folder (to get the file names)
    my @contents = <$folder/*>;

    # For each filename in the list, if it matches, print it
    foreach my $item ( @contents ) {
        if ($item =~ /^$folder(?=.*(offers|cleared))(?=.*(regup|regdn)).*csv$/i){
            print "$item\n";
        }
    }
}

尝试更短/更清洁的东西:

foreach my $folder ( @folders ) {
    # glob the contents of the folder (to get the file names)
    my @contents = <$folder/*>;

    # Seems to determine that there are four matches in each folder
    # but then prints the first matching filename four times
    my $single = join("\n", @contents);
    for ($single =~ /^$folder(?=.*(offers|cleared))(?=.*(regup|regdn)).*csv$/im) {
        print "$&\n";#"Matched: |$`<$&>$'|\n\n";
    }
}

我尝试了使用其他选项(/ img,/ ig等)的正则表达式的其他格式,并将正则表达式的输出发送到数组,但没有任何工作正常。我对Perl并不擅长,所以我很肯定我错过了一些让整个程序更有效率的大好机会。谢谢!

2 个答案:

答案 0 :(得分:1)

仅收集包含offerscleared AND regupregdn

的文件名
my @contents = grep { /offers|cleared/i && /regup|regdn/i } <$folder/*>;

答案 1 :(得分:0)

为什么使用join而不是循环会更短或更干净?我会说它让它变得更复杂。你似乎在做什么只是根据条件松散地匹配

  • 名称包含offerscleared
  • 名称包含regupregdn
  • 名称以.csv结尾。

那么为什么不这样做呢:

if ( $file =~ /offers|cleared/i and
     $file =~ /regup|regdn/i    and
     $file =~ /csv$/i) 

您可能会对以下内容感兴趣:

use strict;
use warnings;
use File::Find;

my $dir = "/some/dir";
my @files;
find(sub { /offers|cleared/i && 
           /regup|regdn/i &&
           /csv$/i && push @files, $File::Find::name }, $dir);

哪个将完全排除readdir和其他循环的使用。 File::Find是递归的。