Это может быть несколько упрощено (я также внес несколько стилистических изменений для улучшения читабельности):
my @data = (
[ qw /2012-02-21_09:43:43/ ],
[ qw /2012-02-21_09:43:43/ ]
);
my %counts;
foreach my $words (@data) {
my ($day, $hour) = ($words->[0] =~ /(\d{4}-\d{2}-\d{2})_(\d+):/ );
$counts{$day}->{$hour} += 1;
}
foreach my $day (keys %counts) {
foreach my $hour (keys %{ $counts{$day} }) {
print "Hour count for $day:$hour is: $counts{$day}->{$hour}\n";
}
}
Рабочая часть цикла, которая является центральной в вашем запросе, такова:
my ($day, $hour) = ($words->[0] =~ /(\d{4}-\d{2}-\d{2})_(\d+):/ );
# You don't need minutes/seconds, so don't match them
# On the other hand, it's better to match YYYY/MM/DD explicitly!
# A regexp match in a list context will return a list of captures!
# e.g. ($1, $2, ...)
$counts{$day}->{$hour} += 1;
# You need to merely add 1 to a value. No need to push ones on a list.
# Please note that if the data is not guaranteed to be perfectly formatted,
# you need to defend against non-matches:
$counts{$day}->{$hour} += 1 if (defined $day && defined $hour);
Вот тот же код с добавленными комментариями, поясняющий, почему я сделал стилистические изменения:
my @data = ( # Don't use @a - variable name should have meanings
[ qw /2012-02-21_09:43:43/ ], # Not sure why you are using an array ref with
[ qw /2012-02-21_09:43:43/ ], # just 1 element, but let's pretend that is OK
);
my %counts;
foreach my $words (@data) { # Almost never rely on $_ - less readable
my ($day, $hour) = ($words->[0] =~ /(\d{4}-\d{2}-\d{2})_(\d+):/ ;
$counts{$day}->{$hour} += 1; # You can omit "->" but that's less readable
}
foreach my $day (keys %counts) { # Always localize your variable to the block they need
foreach my $hour (keys %{ $counts{$day} }) {
print "Hour count for $day:$hour is: $counts{$day}->{$hour}\n";
}
}