#!/usr/bin/perl -w use strict; # Compute average of second and further elements of array of arrays, except for # last sub-array. Just the simple successive summation is used, so this is # suited only for values that do not differ hugely in size. # -> Array ref # <- List of averages sub avgbut1 { my \$ary= shift; my @sums= @{\$\$ary[0]}; shift @sums; for (@\$ary[1..\$#\$ary-1]) { for my \$ind (0..\$#sums) { \$sums[\$ind] += \$\$_[\$ind+1]; } } my \$count= @\$ary - 1; for (@sums) { \$_ /= \$count; } return @sums; } if( @ARGV < 2 || \$ARGV[0] =~ /^--?h(?:elp)?\$/i ) { print < [ ] Computes the moving average of columns in space-separated numerical text files. All values whose first column is within of the output time/position are averaged. Results are output at every . '#' is recognised as starting a comment in the input. EOF exit; } my (\$range, \$step)= splice(@ARGV, 0, 2); my @current; my (\$outind, \$outpos); while( <> ) { s/#.*\$//; next if /^\s*\$/; push @current, [ split ]; if( ! defined \$outind ) { \$outind= int( (\$current[-1][0] + \$step/2.0) / \$step ); \$outpos= \$step * \$outind; } elsif( \$current[-1][0] > \$outpos + \$range/2.0 ) { shift @current while \$current[0][0] < \$outpos - \$range/2.0; if( @current > 1 ) { print \$outpos, "\t\t", join("\t\t", avgbut1(\@current)), "\n"; } ++\$outind; \$outpos= \$step * \$outind; } } push @current, undef; while( 13 ) { shift @current while @current > 1 && \$current[0][0] < \$outpos - \$range/2.0; last if @current == 1 || \$outpos > \$current[-2][0]; print \$outpos, "\t\t", join("\t\t", avgbut1(\@current)), "\n"; ++\$outind; \$outpos= \$step * \$outind; }