我正在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个字符之后的数字而不是另一个字符。) 我已经看过Stackoverflow或perlmonks处理排序的无数问题,但我无法找到问题的答案。
编辑:我正在使用Windows机器。答案 0 :(得分:6)
你几乎就在那里......“。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 ^^
答案 1 :(得分:3)
你可以给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
答案 2 :(得分:2)
我相信substr($ a,4)正在返回&#34; 100.csv&#34;在你的例子中,所以你需要修剪.csv后缀。