2013-12-16 3 views
1

Что мне нужно сделать, это написать скрипт, который будет читать в списке каталогов , а затем отсортировать их, а последний каталог будет «удален».сортировка массива PERL по дате на ASCII

my $ last_one = pop @sorted;

Затем, что последний каталог будет удален - с системой ("RM- ВЧ $ 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 } 

Однако я имею много проблем сортировки каталогов. -.. они написаны этот формат Это фактический выход

2013Nov12 
2013Sep14 
2013Jul15 
2013Jan20 
2013Sep11 
2013May31 
2013Jul04 
2012Dec09 
2013Oct12 
2013Oct09 
2012Dec27 
2013Nov28 
2013Mar24 
2013Jun06 
2013Jun25 
+0

Вы говорите, что «сортировка по ASCII» в заголовке, но я предполагаю, что вы действительно хотите, чтобы сортировать по дате (т.е. самого старого до нового или наоборот)? – ThisSuitIsBlackNot

+1

Сортировка не имеет смысла, если вы просто хотите найти самое старое. – ikegami

+0

проблема в том, что она сортируется по ascii, а не по дате - да, что мне нужно, это старейшая дата-каталог. – capser

ответ

2

сортировка() принимает блок кода, где вы можете определить свой собственный алгоритм сортировки Просто конвертировать реж имен отметки времени, и вы должны идти Это.. будет немного например
sort { date2stamp($a) <=> date2stamp($b) } @unsorted
И внутри date2stamp sub используется POSIX :: mktime(), чтобы создать правильную метку времени для строки даты.

3

Вам понадобится функция преобразования имен каталогов в даты (разделение информации о дате на вещи, которые вы можете сортировать: Год, Месяц, День).

Вот пример

sub parsedate { 
    my $name = shift; 
    my %months = ('Jan'=> 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, 
    'May'=> 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 
    'Sep'=> 9, 'Oct' => 10, 'Nov' => 11, 'Dec' => 12); 

    my ($y,$m,$d); 
    $name =~ m/^(\d{4})(\w{3})(\d{2})$/ 
    and ($y,$m,$d) = ($1,$months{$2},$3) 
    or die "file name $name doesn't match"; 

    return sprintf("%04d%02d%02d",$y,$m,$d); 
} 

Теперь вы можете отсортировать их с помощью нового суб parsedate.

my @sorted_dir = sort {parsedate($a) <=> parsedate($b)} @unsorted; 
2

преобразовать название месяца в число, а затем сделать ряд из YMD Затем сортировать числа численно «Преобразование Шварца» используется для крепления номера к имени файла

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

my %monthval=qw(Jan 01 Feb 02 Mar 03 Apr 04 May 05 Jun 06 Jul 07 Aug 08 Sep 09 O 
ct 10 Nov 11 Dec 12); 


my @in=qw(2013Nov12 
2013Sep14 
2013Jul15 
2013Jan20 
2013Sep11 
2013May31 
2013Jul04 
2012Dec09 
2013Oct12 
2013Oct09 
2012Dec27 
2013Nov28 
2013Mar24 
2013Jun06 
2013Jun25); 

my @sorted = map{$_->[0]} sort { $a->[1] <=> $b->[1]} map { my ($y,$m,$d)=/(\d{ 
4})(\w{3})(\d{2})/; [$_,"$y".$monthval{$m}."$d"]} @in; 

foreach my $name (@sorted) { 
    print "$name\n"; 
} 
5

Предположим, что существует функция convert_date, которая преобразует вашу дату в формат YYYYMMDD. Если бы у вас было это, простое сравнение строк было бы самым старым.

my ($oldest) = 
    sort { convert_date($a) cmp convert_date($b) } 
    @dirs; 

Быстрее:

my ($oldest) = 
    map $_->[0], 
    sort { $a->[1] cmp $b->[1] } 
    map [ $_, convert_date($_) ], 
    @dirs; 

быстрый:

my ($oldest) = 
    map substr($_, 8), 
    sort 
    map convert_date($_) . $_, 
    @dirs; 

Но сортировки (O (N журнал N)) является расточительным способом поиска одного элемента (O (N)).

my $oldest = $dirs[0]; 
for (@dirs) { 
    $oldest = $_ if convert_date($_) lt $oldest; 
} 

Быстрее?

use List::Util qw(minstr); 
my $oldest = substr(minstr(map { convert_date($_) . $_ } @dirs), 8); 

Теперь все, что осталось пишет 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); 
} 

Вы также можете использовать 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'); 
} 
+0

Удивительное объяснение. Вы не возражаете, я спрашиваю, почему вы используете «Карп»? Это по привычке или есть выигрыш (всегда говорят о сценарии OP)? – foibs

+0

@foibs, потому что Carp предоставляет 'croak', что здесь уместно. – ikegami

+0

Извините, я не был ясен. Я имел в виду, как «croak» более подходит, чем «умереть». Спасибо – foibs

Смежные вопросы