I have a bash script which works when called like this: ./stats.sh -rows test_file
The program basically calculates row averages and medians & column averages and medians. Now to the program I want to pass file as standard input. but when I am running this code it prints "you have 2 provide 2 arguments"
. what changes should I have to make so that the code takes stdin as a file. I mean to say If I want to run the script I can run it by this way as well ./stats.sh -rows < test_file
. I want to get this functionality!!
the input file is: (columns separated by tabs)
93 93 93 93 93 93 93 93 100
73 84 95 83 72 86 80 97 100
85 0 82 75 88 79 80 81 100
85 0 87 73 88 79 80 71 100
80 81 83 63 100 85 63 68 100
53 57 61 53 70 61 73 50 100
55 54 41 63 63 45 33 41 100
53 55 43 44 63 75 35 21 100
100 100 100 100 100 100 100 100 100
the code which I worked on is this:
#! /bin/bash
clear
#the arguments below will check for your command line args whether you have provided corrctly or not
flag=0
if [ "$#" -eq 0 ]; then
echo "Please provide arguments"
elif [ "$#" -lt 2 ]; then
echo "You have to provide 2 arguments" >&2
exit 1
elif [ "$#" -gt 2 ]; then
echo "${#}"
FILE= "${4}"
if [ -f "${FILE}" ]; then
flag=1
else
echo "You have provided more number of arguments" >&2
fi
exit 1
else
echo "You have entered correct number of arguments"
fi
# the below code is the case code which checks whether you have -r/-rows or -c/-cols
option="${1}"
l1=0
sorted=()
case ${option} in
-rows| -r| -r*)
if [ $flag -eq 1 ]; then
FILE="${4}"
else
FILE="${2}"
fi
clear
echo "Average Median"
lines=$(wc -l < "$FILE")
while read -r line
do
len=0
tot=0
name=$line
#array=(`echo $name | cut -d " " --output-delimiter=" " -f 1-`)
IFS=' ' read -a array <<< "$name" #if any error comes that might be with this line just check the spaces in the speech marks they should be 4 spaces as it is checking for tabs
for element in "${array[@]}"
do
tot=$(expr $tot + $element)
#let tot+=$element #you can use this as well to get the totals
let len+=1
done
avg=($(printf "%.0f" $(echo "scale=2;$tot/$len" | bc)))
readarray -t sorted < <(for a in "${array[@]}"; do echo "$a"; done | sort)
no=`expr $len % 2`
if [ $no -eq 0 ]; then
mid=`expr $len / 2`
echo "$avg ${sorted[$mid]}"
else
if [ $lines -lt 2 ]; then
mid=`expr $len / 2`
echo "$avg ${sorted[$mid]}"
else
l1=`expr $len / 2`
mid=`expr $l1 + 1`
echo "$avg ${sorted[$mid]}"
fi
fi
unset "array[@]"
unset "sorted[@]"
done < "$FILE"
;;
-cols| -c| -c*)
if [ $flag -eq 1 ]; then
FILE="${4}"
else
FILE="${2}"
fi
#echo "cols"
#echo "File name is $FILE"
cols=$(head -1 "$FILE" | tr "\t" '\n' | wc -l)
lines=$(wc -l < "$FILE")
IFS=$'\t\n' read -d '' -r -a lins < "$FILE"
while read line;do
x=1
read -a array <<< "$line" ##Split the line by spaces
for element in "${!array[@]}"
do
row[${element}]=$((${row[${element}]}+${array[$element]})) ##For each column increment array variable by number in the column.
((x++))
done
done < "$FILE"
echo "Averages: "
for element in ${row[@]}
do
mean= printf "%.0f" $(echo "scale=2;$element/$lines" | bc) ##bc prints floating point numbers and then we round of using scale and .0f
echo -n "$mean "
done
printf "\n"
echo "Medians: "
for ((i=0;i<$cols;i++))
do
carr=()
for ((j=i;j<$lines * $cols;j=j+$cols))
do
carr+=(${lins[$j]})
done
IFS=$' \n' csort=($(sort <<<"${carr[*]}"))
no=`expr $lines % 2`
if [ $no -eq 0 ]; then
mid=`expr $lines / 2`
echo -n "${csort[$mid]} "
else
if [ $lines -lt 2 ]; then
mid=`expr $lines / 2`
echo -n "${csort[$mid]} "
else
l1=`expr $lines / 2`
mid=`expr $l1 + 1`
echo -n "${csort[$mid]} "
fi
fi
done <<<"$lins"
printf "\n"
;;
*)
echo "`basename ${0}`:usage: [-r|-rows rows] | [-c|-cols columns]"
exit 1 # Command to come out of the program with status 1
;;
esac
trap "echo ;exit" 1 2