Thursday, April 27, 2006

sum/avg/max/min/percent of column(s)

#! /bin/sh
#
# Name: 
#   colmath.sh
# 
# Description: 
#   Calculate the average/sum/min/max/percent of column
#   position(s), default to column 1 if not given
#   Usage: colmath.sh <file> <avg|max|min|percent|sum> [col] ...
#
# Written by: 
#   Chi Hung Chan, chihung@singnet.com.sg
#
# Examples:
#    $ ./colmath.sh some.log sum 7 9 11 13
#    36 66 164 5364
#    $ ./colmath.sh some.log percent 7 9 11 13
#    0.64 1.17 2.91 95.28
#    $ ./colmath.sh some.log max 7 9 11 13
#    2 2 2 52
#    $ ./colmath.sh some.log min 7 9 11 13
#    0 0 0 0


if [ $# -eq 0 ]; then
 echo "Usage: $0 <file> <avg|max|min|percent|sum> [col] ..." 1>&2
 exit 1
fi


# check file existence
file=$1
if [ ! -f $file ]; then
 echo "Error. cannot find $file" 1>&2
 exit 2
fi
shift


#
# validate action
#
action="$1"
case $action in
 sum|avg|min|max|percent)
  ;;
 *)
  echo "Error. Invalid action \"$action\"" 1>&1
  exit 3
  ;;
esac
shift


if [ $# -eq 0 ]; then
 args="1"
else 
 args="$@"
fi


#
# calculate percentage
# run itself to get the sum for each column and calculate the percentage
#
if [ "$action" = "percent" ]; then
 $0 $file sum $args | awk '
 {
  for ( i=1 ; i<=NF ; ++i ) {
   sum+=$i
   data[i]=$i
  }
 } 
 END{
  for ( i=1 ; i<=NF ; ++i ) {
   printf("%.2f ",100*data[i]/sum)
  }
 }'
 exit
fi



for i in $args
do
 case $action in
 sum)
  awk '
  {
   sum+=$'$i'
  } 
  END {
   printf("%d ",sum)
  }' $file
  ;;
 avg)
  awk '
  {
   sum+=$'$i'
  } 
  END {
   printf("%f ",sum/NR)
  }' $file
  ;;
 min)
  awk '
  BEGIN {
   min=sprintf("%d",2^32-1)
  }
  {
   if ( min > $'$i' ) {
    min=$'$i'
   }
  } 
  END {
   printf("%d ",min)
  }' $file
  ;;
 max)
  awk '
  BEGIN {
   max=sprintf("-%d",2^32-1)
  }
  {
   if ( max < $'$i' ) {
    max=$'$i'
   }
  } 
  END {
   printf("%d ",max)
  }' $file
  ;;
 esac
done

0 Comments:

Post a Comment

<< Home