#!/bin/sh -- # A comment mentioning perl, indented for bash's sake. eval 'exec perl -S $0 ${1+"$@"}' if 0; chop($Program = `basename $0`); $Usage = <<"END"; $Program: sum up numbers and optionally perform averages. Usage: $Program Options: -t place "Total:" string in output line, -n to turn off. -a perform averages (ave, dev, stderr). -pm with plus minus. Notes: The standard error estimate assume all the data are statistically independent of course. END $no_total = 1; $do_ave = 0; $do_chi = 0; $plus_minus = 0; LOOP: while (@ARGV) { $_ = shift; CASE: { /^-n/ && ($no_total = 1, last CASE); /^-t/ && ($no_total = 0, last CASE); /^-a/ && ($do_ave = 1, last CASE); /^-chi/ && ($do_ave = 1, $do_chi = 1, last CASE); /^-pm/ && ($do_ave = 1, $plus_minus = 1, last CASE); /^-d$/ && ($Debug = 1, last CASE); /^--$/ && (last LOOP); # -- means end of switches /^-(-.*)$/ && (unshift(@ARGV, $1), last CASE); /^(-h|-help)$/ && ((print STDERR $Usage), exit 0, last CASE); if ( /^-(..+)$/ ) { # split bundled switches: local($y, $x) = ($1, ''); foreach $x (reverse(split(//, $y))) { unshift(@ARGV,"-$x") }; last CASE; } /^-/ && ((print STDERR "Invalid arg: $_\n$Usage"), exit 1, last CASE); unshift(@ARGV,$_); last LOOP; } } $sum = 0.0; $dev = 0.0; $n = 0; while (<>) { chop; $x = &trim($_); next if $x eq ''; if ( $do_chi ) { ($x, $err) = split(/\s+/, $_); $Vals[$n] = $x; $Errs[$n] = $err; } $n++; $sum = $sum + $x; if ( $do_ave ) { $dev += ($x ** 2); } } if ( $do_ave ) { $n = 1 if $n == 0; $ave = $sum / $n; $dev = $dev / $n; $dev = $dev - ($ave ** 2); if ( $dev > 0.0 ) { $dev = sqrt($dev); } else { $dev = 0.0; } $err = $dev/sqrt($n); $ave = sprintf("%12.6f", $ave); $dev = sprintf("%12.6f", $dev); $err = sprintf("%12.6f", $err); } else { $sum = sprintf("%12.5f",$sum); } if ( $do_ave ) { $ave =~ s/^\s*//; $dev =~ s/^\s*//; $err =~ s/^\s*//; $chi = ''; if ( $do_chi ) { $chi = 0.0; for ($i=0; $i< @Errs; $i++) { $dx = ($Vals[$i] - $ave)/$Errs[$i]; $chi += $dx ** 2; } $chi = sprintf("%12.6f", $chi); $chi =~ s/^\s*//; $chi = " chi^2: $chi"; } if ( $plus_minus ) { print "$ave +/- $err dev\[$n]: $dev$chi\n"; } else { print "ave: $ave dev: $dev err\[$n]: $err$chi\n"; } } elsif ( $no_total ) { $sum = &trim($sum); print "$sum\n"; } else { print "Total: $sum\n"; } exit 0; sub trim { local($x) = @_; $x =~ s/^\s*//; $x =~ s/\s*$//; return $x; }