#!/usr/bin/perl -w use strict; use Getopt::Long; use POSIX; sub parseint { return $_[0]; } sub parsemsec { return $_[0]/1000; } sub parsetime { my @f= split /:/, $_[0]; my $t=0; for my $f (@f) { $t *= 60; $t += $f; } return $t; } sub parsedate { my @f= split /[-\/]/, $_[0]; return POSIX::mktime(0,0,0,$f[0], $f[1]-1, $f[2]-1900); } sub parsedatetime { my @f= split /[-\/:,]/, $_[0]; return POSIX::mktime($f[5],$f[4],$f[3],$f[2], $f[1]-1, $f[0]-1900); } sub parsetimegroup { our %types= ( sec=>1, min=>60, hour=>3600, hr=>3600, day=>86400, week=>7*86400, month=>30.5*86400, year=>365.2422*86400 ); if ($_[0] =~ /(\d*)([a-z]+)/) { my ($num, $type)= ($1,$2); die "unknown type: $type\n" if (!exists $types{$type}); $num= 1 if !defined $num || $num eq ''; return $num * $types{$type}; } die "unknown type: $_[0]\n"; } my $xcolumnparser=\&parseint; my $groupparser=\&parseint; my $grouping=1; my $outputzeros; # todo - implement GetOptions( "a"=>\$outputzeros, "m"=>sub { $xcolumnparser=\&parsemsec; $groupparser=\&parsetimegroup; }, "t"=>sub { $xcolumnparser=\&parsetime; $groupparser=\&parsetimegroup; }, "d"=>sub { $xcolumnparser=\&parsedate; $groupparser=\&parsetimegroup; }, "dt"=>sub { $xcolumnparser=\&parsedatetime; $groupparser=\&parsetimegroup; }, "g=s"=>\$grouping, ) or die usage(); $grouping= $groupparser->($grouping); sub usage { return <<__EOF__ Usage: group [-a] [-m -t | -d] [-g GROUPING] -a : list zero's too -t : first column is a time -d : first column is a date ( d-m-y ) -dt : first column is a date+time ( y-m-d,h:m:s ) -m : first column is in msecs -g : specify grouping, like sec or 10sec or 1000 __EOF__ } my %x; while (<>) { s/^\s+//; s/\s+$//; my @f=split /\s+/, $_; my $x= $xcolumnparser->($f[0]) ; if ($grouping!=1) { $x = int($x/$grouping); } else { $x = int($x); } $x{$x} += $f[1]; } if ($outputzeros) { my @x= sort {$a<=>$b} keys %x; for (my $x= $x[0] ; $x<$x[-1] ; $x += $grouping) { $x{$x} ||=0; } } for my $x (sort {$a<=>$b} keys %x) { printf("%8s %8d\n", $x, $x{$x}); }