Home > Software design >  How do I calculate row sum in Bash without awk?
How do I calculate row sum in Bash without awk?

Time:03-20

I have a question, how i can calculate row sum in Bash without awk, only f.e with loops, but if I have in input some pipes? It seems:

| 11 14 |
| 13  7 |

Thanks!

CodePudding user response:

Say your input is in the file /tmp/input.txt (I added a decimal and negative number just because.)

$ cat /tmp/input.txt
| 11   -14 |
| 13.4   7 |

First, remove stuff that's not a number, a space, or a newline:

$ tr -sc '[- 0-9.]\n' ' ' < /tmp/input.txt 
 11 -14 
 13.4 7 

Next, remove leading/trailing spaces:

$ tr -sc '[- 0-9.]\n' ' ' < /tmp/input.txt | sed 's/^ //;s/ $//'
11 -14
13.4 7

Now, replace the remaining spaces with a operator:

$ tr -sc '[- 0-9.]\n' ' ' < /tmp/input.txt | sed 's/^ //;s/ $//;s/ / /g'
11 -14
13.4 7

Finally, send all that into the calculator:

$ tr -sc '[- 0-9.]\n' ' ' < /tmp/input.txt | sed 's/^ //;s/ $//;s/ / /g' | bc
-3
20.4

CodePudding user response:

You can also use dc

tr -d '|' < file.txt | while read l; do echo $l   p | dc; done

CodePudding user response:

You can do this entirely in bash without any additional utilities simply by reading each line into an array and then looping over each element in the array checking if the element is all digits and adding the number to the sum for the line. For example you could do:

#!/bin/bash

[ -z "$1" ] && {  ## validate 1 argument given for filename
  printf "error: filename required as argument.\n" >&2
  exit 1
}

file="$1"   ## assign argument to file

[ -s "$file" ] || {  ## validate file not empty
  printf "error file not found or empty.\n" >&2
  exit 1
}

while read -ra arr; do                               ## read line into arr
  sum=0                                              ## zero sum for line
  for i in ${arr[@]}; do                             ## loop each element
    [[ $i =~ ^[[:digit:]] $ ]] && sum=$((sum   $i))  ## all digits add to sum
  done
  echo "sum: $sum"                                   ## output sum
done < "$file"

(note: if negative numbers are possible, you can handle that with a simple check for zero or more '-' characters before all digits with -*[[:digit:]] )

You don't need to know the number of numeric elements beforehand, it simply loops over each whitespace separated word and checks if the word is comprised of all digits before adding it to the sum.

Example Use/Output

With the script in sum.sh and your example input in file, your output would be:

$ bash sum.sh file
sum: 25
sum: 20
  • Related