#!/usr/bin/env perl # # aggr - aggregate numbers found in input # # $Id$ # replaces the numbers with their aggregate, per column # # this is useful - try 'ls -s | aggr max' for a demo # I probably want more flexibility as to what it aggregates and what it doesn't use warnings; use strict; use Getopt::Std; my %opt; getopts( 'hp', \%opt ); $| = 1; # unbuffer output my %op = ( '+' => sub { $_[0] + $_[1] }, '-' => sub { $_[0] - $_[1] }, '*' => sub { $_[0] * $_[1] }, 'min' => sub { $_[0] < $_[1] ? $_[0] : $_[1] }, 'max' => sub { $_[0] > $_[1] ? $_[0] : $_[1] } ); my $default_opcode = '+'; my $opcode = shift(@ARGV); my $ops = join( ', ', sort keys %op ); $opt{h} and HELP_MESSAGE(); if ( !defined($opcode) || !defined( $op{$opcode} ) ) { $opcode = $default_opcode; warn "operation not specified, using $opcode\n"; } my $op = $op{$opcode} // die "BUG: undefined operation $opcode\n"; sub HELP_MESSAGE { print STDERR <) { @line = split(/(-?\d+)/); for ( my $i = 0, my $j = ( $line[0] =~ /\d/ ) ? 0 : 1 ; $j <= $#line ; ++$i, ++$j, ++$j ) { $line[$j] = ( $total{$i} = defined $total{$i} ? &$op( $total{$i}, $line[$j] ) : $line[$j] ); } print join( '', @line ) if $progressive; } print join( '', @line ) if !$progressive && @line;