#!/usr/bin/perl use 5.010; use strict; use warnings; # Data reducer collecting values in a list my $collect = { init => [], step => sub { [ @{$_[0]}, $_[1] ] }, fini => sub { '[' . join(', ', @{$_[0]}) . ']' } }; # Data reducer averaging numerical values my $average = { init => [ 0, 0 ], step => sub { [ $_[0]->[0] + 1, $_[0]->[1] + $_[1] ] }, fini => sub { $_[0]->[1] / $_[0]->[0] } }; # Mapping from field indices to data reducers my @reducers = ( $collect, $collect, $average, $average, $average, $average ); # Read data my %data = (); while () { my ($stamp, $d, $m, $y, @fields) = split /\s+/; push @{$data{$stamp}}, \@fields; } # Reduce and print data foreach my $stamp (sort keys %data) { my @accumulators = map { $_->{init} } @reducers; foreach my $fields (@{$data{$stamp}}) { @accumulators = map { $reducers[$_]->{step}->($accumulators[$_], $fields->[$_]) } $[ .. $#reducers; } @accumulators = map { $reducers[$_]->{fini}->($accumulators[$_]) } $[ .. $#reducers; say join("\t", $stamp, @accumulators); } __DATA__ 1094000940 01 09 2004 N49390 E009202 12360 -3 320 017 1094000940 01 09 2004 N49410 E009203 11650 -2 305 016 1094000940 01 09 2004 N49431 E009204 11120 -2.5 339 016 1094001000 01 09 2004 N49451 E009205 10990 -2.2 325 018 1094001000 01 09 2004 N49470 E009199 10460 -1.5 291 018 1094001000 01 09 2004 N49489 E009184 9550 -5.2 250 010