Last active
August 29, 2015 14:08
-
-
Save nlitsme/6d1da23538f8a14348f3 to your computer and use it in GitHub Desktop.
add numbers group by specific column
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl -w | |
use strict; | |
use Getopt::Long; | |
use POSIX; | |
# todo: convert back to time in output | |
sub parseint { | |
return $_[0]; | |
} | |
sub outputint { | |
return int($_[0]); | |
} | |
sub parsemsec { | |
return $_[0]/1000; | |
} | |
sub outputmsec { | |
return $_[0]*1000; | |
} | |
sub parsetime { | |
my @f= split /:/, $_[0]; | |
my $t=0; | |
for my $f (@f) { | |
$t *= 60; | |
$t += $f; | |
} | |
return $t; | |
} | |
sub outputtime { | |
my $t=shift; | |
return sprintf("%02d:%02d:%02d", int($t/3600), int($t/60)%60, $t%60); | |
} | |
sub parsedate { | |
my @f= split /[-\/]/, $_[0]; | |
return POSIX::mktime(0,0,0,$f[2], $f[1]-1, $f[0]-1900); | |
} | |
sub outputdate { | |
my $t= shift; | |
my @tm= POSIX::gmtime($t); | |
return sprintf("%04d-%02d-%02d", $tm[5]+1900, $tm[4]+1, $tm[3]); | |
} | |
sub parsedatetime { | |
my @f= split /[-\/:,]/, $_[0]; | |
return POSIX::mktime($f[5],$f[4],$f[3],$f[2], $f[1]-1, $f[0]-1900); | |
} | |
sub outputdatetime { | |
my @tm= POSIX::gmtime(shift); | |
return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $tm[5]+1900, $tm[4]+1, $tm[3], $tm[2], $tm[1], $tm[0]); | |
} | |
sub parsetimegroup { | |
our %types= ( s=>1, 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 in $_[0]\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 $xcolumnoutput=\&outputint; | |
my $groupparser=\&parseint; | |
my $grouping="1s"; | |
my $outputzeros; # todo - implement | |
GetOptions( | |
"a"=>\$outputzeros, | |
"m"=> sub { $xcolumnoutput=\&outputmsec; $xcolumnparser=\&parsemsec; $groupparser=\&parsetimegroup; }, | |
"t"=> sub { $xcolumnoutput=\&outputtime; $xcolumnparser=\&parsetime; $groupparser=\&parsetimegroup; }, | |
"d"=> sub { $xcolumnoutput=\&outputdate; $xcolumnparser=\&parsedate; $groupparser=\&parsetimegroup; }, | |
"dt"=>sub { $xcolumnoutput=\&outputdatetime; $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 %8f\n", $xcolumnoutput->($x*$grouping), $x{$x}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment