在 Perl 中对文件名进行排序?

Sorting names of files in Perl?

我正在用 Perl 编写一个脚本,我想 运行 在给定目录中的所有 .csv 文件上。文件名的类型为:CCCC0.csv, CCCC1.csv, ..., CCCC198.csv。但是,我希望 Perl 首先 运行 文件 CCCC0.csv 上的脚本,而不是 CCCC1.csv 等...所以,基本上,根据末尾数字的递增值文件名。 如果我写:

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

my $file;
my @files = <*.csv>;
my @orderedfiles = sort @files;
for $file (@orderedfiles) {

... do stuff

}

它首先 运行 在 CCCC100.csv 而不是 CCCC11.csv 而如果我写

#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

my $file;
my @files = <*.csv>;
my @orderedfiles = sort { substr($a, 4) <=> substr($b, 4)  } @files;
for $file (@orderedfiles) {

... do stuff

}

它给我一个错误,告诉我我没有订购数字(我假设他不明白这是 4 个字符之后的数字而不是另一个字符。) 我已经查看了关于 Whosebug 或 perlmonks 的无数问题,但我一直无法找到我的问题的答案。

编辑:我正在使用 windows 机器。

我相信 substr($a, 4) 在您的示例中返回“100.csv”,因此您仍然需要 trim 关闭它的 .csv 后缀。

您快到了...“.CSV”仍然存在。最好使用正则表达式来读取数字字符。

my @sorted = sort { ($a =~ /(\d+)/)[0] <=> ($b =~ /(\d+)/)[0] } @files;

有一个成语叫Schwartzian Transform也可以做到这一点,虽然它需要CS专业才能理解:D

my @sorted = map  { $_->[0] }             # return the sorted file names
                                          #
             sort { $a->[1] <=> $b->[1] } # sort on the numeric portion
                                          #
             map  { [$_, /(\d+)/] }       # wrap the file names in a temporary 
             @files;                      #   array with their numeric portions.

                                          # ^^ read from bottom to top ^^

您可以 Sort::Key::Natural 试一试。来自简介:

use Sort::Key::Natural qw(natsort);

my @data = qw(foo1 foo23 foo6 bar12 bar1
              foo bar2 bar-45 foomatic b-a-r-45);

my @sorted = natsort @data;

print "@sorted\n";
# prints:
#   b-a-r-45 bar1 bar2 bar12 bar-45 foo foo1 foo6 foo23 foomatic