Skip to content

Instantly share code, notes, and snippets.

@nlitsme
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nlitsme/6d1da23538f8a14348f3 to your computer and use it in GitHub Desktop.
Save nlitsme/6d1da23538f8a14348f3 to your computer and use it in GitHub Desktop.
add numbers group by specific column
#!/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