5

I'm trying to write a bash script that calculates the average of numbers by rows and columns. An example of a text file that I'm reading in is:

1 2 3 4 5
4 6 7 8 0

There is an unknown number of rows and unknown number of columns. Currently, I'm just trying to sum each row with a while loop. The desired output is:

1 2 3 4 5 Sum = 15
4 6 7 8 0 Sum = 25

And so on and so forth with each row. Currently this is the code I have:

while read i
do
  echo "num: $i"
  (( sum=$sum+$i ))
  echo "sum: $sum"
done < $2

To call the program it's stats -r test_file. "-r" indicates rows--I haven't started columns quite yet. My current code actually just takes the first number of each column and adds them together and then the rest of the numbers error out as a syntax error. It says the error comes from like 16, which is the (( sum=$sum+$i )) line but I honestly can't figure out what the problem is. I should tell you I'm extremely new to bash scripting and I have googled and searched high and low for the answer for this and can't find it. Any help is greatly appreciated.

1
  • I think you want sum=$(($sum + $i)) Commented Oct 8, 2015 at 4:52

4 Answers 4

4

You are reading the file line by line, and summing line is not an arithmetic operation. Try this:

while read i
do
  sum=0
  for num in $i
  do
    sum=$(($sum + $num))
  done
  echo "$i Sum: $sum"
done < $2

just split each number from every line using for loop. I hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

You can simplify sum=$(($sum + $num)) to ((sum = sum + num)).
or replace sum=0 by declare -i sum=0 and use sum+=$num with bash.
This worked exactly how I wanted it! Thanks so much.
3

Another non bash way (con: OP asked for bash, pro: does not depend on bashisms, works with floats).

awk '{c=0;for(i=1;i<=NF;++i){c+=$i};print $0, "Sum:", c}'

Comments

0

Another way (not a pure bash):

while read line
do
    sum=$(sed 's/[ ]\+/+/g' <<< "$line" | bc -q)
    echo "$line Sum = $sum"
done < filename

Comments

0

Using the numsum -r util covers the row addition, but the output format needs a little glue, by inefficiently paste-ing a few utils:

paste "$2" \
      <(yes "Sum =" | head -$(wc -l < "$2") ) \
      <(numsum -r "$2") 

Output:

1 2 3 4 5   Sum =   15
4 6 7 8 0   Sum =   25

Note -- to run the above line on a given file foo, first initialize $2 like so:

set -- "" foo
paste "$2" <(yes "Sum =" | head -$(wc -l < "$2") )  <(numsum -r "$2") 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.