在perl中对目录进行排序,考虑数字
我想我需要某种方法来让它工作,但我很难弄清楚,因为perl不是我最强大的语言 我有一个目录,其内容如下:在perl中对目录进行排序,考虑数字,perl,sorting,readdir,Perl,Sorting,Readdir,我想我需要某种方法来让它工作,但我很难弄清楚,因为perl不是我最强大的语言 我有一个目录,其内容如下: album1.htm album2.htm album3.htm .... album99.htm album100.htm 我正试图从这个目录(在本例中为album100.htm)获取编号最高的相册。请注意,文件上的时间戳不是确定事情的可靠方法,因为人们在事后添加旧的“缺失”相册 以前的开发人员只是使用了下面的代码片段,但一旦一个目录中有9个以上的相册,显然就会出现故障 opendir(
album1.htm
album2.htm
album3.htm
....
album99.htm
album100.htm
我正试图从这个目录(在本例中为album100.htm)获取编号最高的相册。请注意,文件上的时间戳不是确定事情的可靠方法,因为人们在事后添加旧的“缺失”相册
以前的开发人员只是使用了下面的代码片段,但一旦一个目录中有9个以上的相册,显然就会出现故障
opendir(DIR, PATH) || print $!;
@files = readdir(DIR);
foreach $file ( sort(@files) ) {
if ( $file =~ /album/ ) {
$last_file = $file;
}
}
如果你只需要找到编号最高的唱片集,你不需要对列表进行排序,只需浏览列表并跟踪最大编号即可
#!/usr/bin/perl
use strict;
use warnings;
my $max = 0;
while ( <DATA> ) {
my ($album) = $_ =~ m/album(\d+)/;
$max = $album if $album > $max;
}
print "album$max.htm";
__DATA__
album1.htm
album100.htm
album2.htm
album3.htm
album99.htm
#/usr/bin/perl
严格使用;
使用警告;
我的$max=0;
而(){
我的($album)=$\u=~ m/album(\d+)/;
$max=$album,如果$album>$max;
}
打印“相册$max.htm”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm
如果您只需要找到编号最高的唱片集,您实际上不需要对列表进行排序,只需运行列表并跟踪最大值即可
#!/usr/bin/perl
use strict;
use warnings;
my $max = 0;
while ( <DATA> ) {
my ($album) = $_ =~ m/album(\d+)/;
$max = $album if $album > $max;
}
print "album$max.htm";
__DATA__
album1.htm
album100.htm
album2.htm
album3.htm
album99.htm
#/usr/bin/perl
严格使用;
使用警告;
我的$max=0;
而(){
我的($album)=$\u=~ m/album(\d+)/;
$max=$album,如果$album>$max;
}
打印“相册$max.htm”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm
要查找最大的数字,请尝试自定义排序
sub sort_files {
(my $num_a = $a) =~ s/^album(\d+)\.htm$/$1/;
(my $num_b = $b) =~ s/^album(\d+)\.htm$/$1/;
return $num_a <=> $num_b;
}
my @sorted = sort \&sort_files @files;
my $last = pop @sorted;
子排序\u文件{
(我的$num_a=$a)=~s/^album(\d+)\.htm$/$1/;
(我的$num_b=$b)=~s/^album(\d+)\.htm$/$1/;
返回$num_a$num_b;
}
我的@sorted=sort\&sort_files@files;
my$last=pop@sorted;
另外,请看一下模块。它将让你只挑选以“album”开头的文件。我发现它比readdir要简单一些。要找到最大的数字,请尝试自定义排序
sub sort_files {
(my $num_a = $a) =~ s/^album(\d+)\.htm$/$1/;
(my $num_b = $b) =~ s/^album(\d+)\.htm$/$1/;
return $num_a <=> $num_b;
}
my @sorted = sort \&sort_files @files;
my $last = pop @sorted;
子排序\u文件{
(我的$num_a=$a)=~s/^album(\d+)\.htm$/$1/;
(我的$num_b=$b)=~s/^album(\d+)\.htm$/$1/;
返回$num_a$num_b;
}
我的@sorted=sort\&sort_files@files;
my$last=pop@sorted;
另外,请看一下模块。它将让你只挑选以“album”开头的文件。我发现它比readdir要简单一些。遇到困难的原因是运算符,
是数字比较,cmp
是默认值,是字符串比较
$ perl -E'say for sort qw/01 1 02 200/';
01
02
1
200
稍加修改,我们就更接近正确:
$ perl -E'say for sort { $a <=> $b } qw/01 1 02 200/';
01
1
02
200
它很酷,因为它既紧凑又高效。遇到困难的原因是运算符,
是数字比较,cmp
是默认值,是字符串比较
$ perl -E'say for sort qw/01 1 02 200/';
01
02
1
200
稍加修改,我们就更接近正确:
$ perl -E'say for sort { $a <=> $b } qw/01 1 02 200/';
01
1
02
200
它很酷,因为它既紧凑又高效。在这里,使用Schwartzian变换:
my @files = <DATA>;
print join '',
map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ m/album(\d+)/, $_ ] }
@files;
__DATA__
album12.htm
album1.htm
album2.htm
album10.htm
my@files=;
打印联接“”,
映射{$\->[1]}
排序{$a->[0]$b->[0]}
映射{[m/album(\d+/,$]}
@档案;
__资料__
相册12.htm
相册1.htm
相册2.htm
相册10.htm
在这里,使用Schwartzian变换:
my @files = <DATA>;
print join '',
map { $_->[1] }
sort { $a->[0] <=> $b->[0] }
map { [ m/album(\d+)/, $_ ] }
@files;
__DATA__
album12.htm
album1.htm
album2.htm
album10.htm
my@files=;
打印联接“”,
映射{$\->[1]}
排序{$a->[0]$b->[0]}
映射{[m/album(\d+/,$]}
@档案;
__资料__
相册12.htm
相册1.htm
相册2.htm
相册10.htm
这里有一个替代解决方案,使用:
使用严格;
使用警告;
使用列表::Util'reduce';
我的$max=减少{
我的($aval,$bval)=($a=~m/专辑(\d+)/,$b=~m/专辑(\d+)/);
$aval>$bval?$a:$b
} ;
打印“最大相册为$max\n”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm
这里有一个替代解决方案,使用:
使用严格;
使用警告;
使用列表::Util'reduce';
我的$max=减少{
我的($aval,$bval)=($a=~m/专辑(\d+)/,$b=~m/专辑(\d+)/);
$aval>$bval?$a:$b
} ;
打印“最大相册为$max\n”;
__资料__
相册1.htm
相册100.htm
相册2.htm
相册3.htm
相册99.htm
这里有一个通用的解决方案:
my @sorted_list
= map { $_->[0] } # we stored it at the head of the list, so we can pull it out
sort {
# first test a normalized version
my $v = $a->[1] cmp $b->[1];
return $v if $v;
my $lim = @$a > @$b ? @$a : @$b;
# we alternate between ascii sections and numeric
for ( my $i = 2; $i < $lim; $i++ ) {
$v = ( $a->[$i] || '' ) cmp ( $b->[$i] || '' );
return $v if $v;
$i++;
$v = ( $a->[$i] || 0 ) <=> ( $b->[$i] || 0 );
return $v if $v;
}
return 0;
}
map {
# split on digits and retain captures in place.
my @parts = split /(\d+)/;
my $nstr = join( '', map { m/\D/ ? $_ : '0' x length() } @parts );
[ $_, $nstr, @parts ];
} @directory_names
;
my@sorted\u列表
=map{$\u->[0]}我们将它存储在列表的最前面,因此可以将其拉出
分类{
#首先测试规范化版本
my$v=$a->[1]cmp$b->[1];
如果$v,则返回$v;
我的$lim=@$a>@$b?@$a:@$b;
#我们交替使用ascii部分和数字部分
对于(我的$i=2;$i<$lim;$i++){
$v=($a->[$i]|| |'')cmp($b->[$i]| |'');
如果$v,则返回$v;
$i++;
$v=($a->[$i]| | 0)($b->[$i]| | 0);
如果$v,则返回$v;
}
返回0;
}
地图{
#按数字分割并将捕获保留在适当位置。
my@parts=split/(\d+)/;
my$nstr=join(“”,映射{m/\D/?$\:'0'x length()}@parts);
[$\$nstr,@parts];
}@directory\u名称
;
这里有一个通用的解决方案:
my @sorted_list
= map { $_->[0] } # we stored it at the head of the list, so we can pull it out
sort {
# first test a normalized version
my $v = $a->[1] cmp $b->[1];
return $v if $v;
my $lim = @$a > @$b ? @$a : @$b;
# we alternate between ascii sections and numeric
for ( my $i = 2; $i < $lim; $i++ ) {
$v = ( $a->[$i] || '' ) cmp ( $b->[$i] || '' );
return $v if $v;
$i++;
$v = ( $a->[$i] || 0 ) <=> ( $b->[$i] || 0 );
return $v if $v;
}
return 0;
}
map {
# split on digits and retain captures in place.
my @parts = split /(\d+)/;
my $nstr = join( '', map { m/\D/ ? $_ : '0' x length() } @parts );
[ $_, $nstr, @parts ];
} @directory_names
;
my@sorted\u列表
=map{$\u->[0]}我们将它存储在列表的最前面,因此可以将其拉出
分类{
#首先测试规范化版本
my$v=$a->[1]cmp$b->[1];
如果$v,则返回$v;
我的$lim=@$a>@$b?@$a:@$b;
#我们交替使用ascii部分和数字部分
对于(我的$i=2;$i<$lim;$i++){
$v=($a->[$i]|| |'')cmp($b->[$i]| |'');
如果$v,则返回$v;
$i++;
$v=($a->[$i]| | 0)($b->[$i]| | 0);
如果$v,则返回$v;
}
返回0;
}
地图{
#按数字分割并将捕获保留在适当位置。
my@parts=split/(\d+)/;
my$nstr=join(“”,映射{m/\D/?$\:'0'x length()}@parts);
[$\$nstr,@parts];
}@directory\u名称
;