cap*_*ser 1 arrays sorting perl
我需要做的是编写一个脚本,它将读入目录列表然后对它们进行排序,最后一个目录将被"关闭".
我的$ last_one = pop @sorted;
然后将删除最后一个目录 - 使用系统("rm- rf $ last_one")或remove_tree($ last_one).
1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4
5 my $dir_to_process = "/production/log/fo/archive/";
6 opendir DH, $dir_to_process or die "Sorry, this is not going to work out $!";
7
8 while (my $name = readdir DH) {
9 next if $name =~ /^\./;
10 push(my @unsorted,$name) ;
11 my @sorted_dir = sort @unsorted;
12 foreach my $sorted (@sorted_dir) {
13 print "$sorted\n";
14 sleep 1 ;
15 }
16
17 }
Run Code Online (Sandbox Code Playgroud)
但是我在排序目录时遇到了很多麻烦 - 它们是用这种格式编写的.这是实际输出.
2013Nov12
2013Sep14
2013Jul15
2013Jan20
2013Sep11
2013May31
2013Jul04
2012Dec09
2013Oct12
2013Oct09
2012Dec27
2013Nov28
2013Mar24
2013Jun06
2013Jun25
Run Code Online (Sandbox Code Playgroud)
让我们假设存在一个convert_date将日期转换为YYYYMMDD格式的函数.如果你有一个,那么简单的字符串比较会找到最旧的.
my ($oldest) =
sort { convert_date($a) cmp convert_date($b) }
@dirs;
Run Code Online (Sandbox Code Playgroud)
快点:
my ($oldest) =
map $_->[0],
sort { $a->[1] cmp $b->[1] }
map [ $_, convert_date($_) ],
@dirs;
Run Code Online (Sandbox Code Playgroud)
最快的:
my ($oldest) =
map substr($_, 8),
sort
map convert_date($_) . $_,
@dirs;
Run Code Online (Sandbox Code Playgroud)
但排序(O(N log N))是找到一个元素(O(N))的浪费方式.
my $oldest = $dirs[0];
for (@dirs) {
$oldest = $_ if convert_date($_) lt $oldest;
}
Run Code Online (Sandbox Code Playgroud)
快点?
use List::Util qw( minstr );
my $oldest = substr(minstr( map { convert_date($_) . $_ } @dirs ), 8);
Run Code Online (Sandbox Code Playgroud)
现在,剩下的就是写作了convert_date.
use Carp qw( croak );
my %month_num_by_en_name = (
Jan => 1, Feb => 2, Mar => 3, Apr => 4,
May => 5, Jun => 6, Jul => 7, Aug => 8,
Sep => 9, Oct => 10, Nov => 11, Dec => 12,
);
sub convert_date {
my ($date) = @_;
my ($y,$m,$d) = $date =~ m/^(\d{4})(\w{3})(\d{2})\z/
or croak("Invalid input");
$m = $month_num_by_en_name{$m}
or croak("Invalid input");
return sprintf("%04d%02d%02d", $y,$m,$d);
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用DateTime :: Format :: Strptime.这样可以更轻松地支持其他语言.
use DateTime::Format::Strptime qw( );
my $format = DateTime::Format::Strptime->new(
pattern => '%Y%b%d',
locale => 'en_US',
on_error => 'croak',
);
sub convert_date {
my ($date) = @_;
return $format->parse_datetime($date)->strftime('%Y%m%d');
}
Run Code Online (Sandbox Code Playgroud)