我选择此解决方案是因为我想在脚本中按日期进行另一种排序。有了关键参考,它会更聪明......
这是您问题的核心部分。您的想法是正确的,但是您以错误的方式实现了它。这就是现在让你陷入困境的原因。
让我们先看看您的数据。你说它是一个日志文件,所以它是基于行的。这个格式我已经编好了。
On 2018/01/12 at 03:00:02 user jerry did stuff.
On 2018/03/01 at 01:00:01 user tom did stuff.
On 2018/03/20 at 00:24:39 user micky did stuff.
On 2018/04/04 at 11:33:33 user agata did stuff.
您的预期输出是 CSV 文件。同样,这是基于行的。
date;time;name
2018/04/04;11:33:33;agata
2018/01/12;03:00:02;jerry
2018/03/20;00:24:39;micky
2018/03/01;01:00:01;tom
因此,您希望数据所在的结构仍然是基于行的。
当您想要按任何列对这些数据进行排序时,您将根据列中的值对 行 进行排序。因此,您确实希望以一种可以轻松访问该行的每个单独列的值的方式存储行。当您在电子表格中查看时,这一点会变得特别清楚。
每一列都是一行的一个值。所以让我们这样做吧。
my @events; # or something like that
while (my $row = <$log_fh>) {
my ( $date, $time, $name ) = parse_row($row); # we don't care about this implementation
push @events, {
date => $date,
time => $time,
name => $name,
};
}
现在我们有了这个数据结构(我用Data::Printer 输出)。
[
[0] {
date "2018/01/12",
name "jerry",
time "03:00:02"
},
[1] {
date "2018/03/01",
name "tom",
time "01:00:01"
},
[2] {
date "2018/03/20",
name "micky",
time "00:24:39"
},
[3] {
date "2018/04/04",
name "agata",
time "11:33:33"
}
]
如您所见,每行有一个哈希引用,其中包含一个日期键、一个时间键和一个名称键。
现在我们可以对这些结构中的任何键进行排序。 That's easy.
my @events_by_name = sort { $a->{name} cmp $b->{name} } @events;
my @events_by_date = sort { $a->{date} cmp $b->{date} } @events;
my @events_by_time = sort { $a->{time} cmp $b->{time} } @events;
然后您可以为每个文件生成 CSV 文件。
open my $fh, '>', 'events_by_name.csv' or die $!;
foreach my $event (@events_by_name) {
print $fh join ';', $event->{name}, $event->{date}, $event->{time};
print $fh "\n";
}
close $fh;
或者您可以根据事件的数量进行迭代,同时打开几个并且只循环一次。
open my $fh_name, '>', 'events_by_name.csv' or die $!;
open my $fh_date, '>', 'events_by_date.csv' or die $!;
for (my $i = 0; $i < @events_by_name; $i++) {
print $fh_name join(
';',
@events_by_name->[$i]->{name},
@events_by_name->[$i]->{date},
@events_by_name->[$i]->{time},
);
print $fh_name "\n";
print $fh_date join(
';',
@events_by_name->[$i]->{name},
@events_by_name->[$i]->{date},
@events_by_name->[$i]->{time},
);
print $fh_date "\n";
}
close $fh_name;
close $fh_date;
您可以通过使用另一个循环来进一步缩短它。
open my $fh_name, '>', 'events_by_name.csv' or die $!;
open my $fh_date, '>', 'events_by_date.csv' or die $!;
for (my $i = 0; $i < @events_by_name; $i++) {
foreach my $fh ($fh_name, $fh_date) {
print $fh join(
';',
@events_by_name->[$i]->{name},
@events_by_name->[$i]->{date},
@events_by_name->[$i]->{time},
);
print $fh "\n";
}
}
close $fh_name;
close $fh_date;
如您所见,在处理线条时保持结构基于线条会更有意义。