3

我正在使用 Perl 来捕获某些指定文件夹中包含某些单词的文件的名称。这些文件名中的关键字是“offers”或“cleared”以及“regup”或“regdn”。换句话说,“offer”或“cleared”之一和“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 不是很好,所以我很肯定我错过了一些让整个过程更有效率的重要机会。谢谢!

4

2 回答 2

1

仅收集这些包含offersor clearedAND regupor的文件名regdn

my @contents = grep { /offers|cleared/i && /regup|regdn/i } <$folder/*>;
于 2013-06-10T17:50:32.843 回答
0

为什么使用连接而不是循环会更短或更简洁?我会说它使事情变得更加复杂。您似乎在做的只是根据条件松散地匹配

  • 名称包含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是递归的。

于 2013-06-10T17:50:56.273 回答