How can I find the sum of the elements of an array in Bash?

45,243

Solution 1

read -a array
tot=0
for i in ${array[@]}; do
  let tot+=$i
done
echo "Total: $tot"

Solution 2

Given an array (of integers), here's a funny way to add its elements (in bash):

sum=$(IFS=+; echo "$((${array[*]}))")
echo "Sum=$sum"

e.g.,

$ array=( 1337 -13 -666 -208 -408 )
$ sum=$(IFS=+; echo "$((${array[*]}))")
$ echo "$sum"
42

Pro: No loop, no subshell!

Con: Only works with integers

Edit (2012/12/26).

As this post got bumped up, I wanted to share with you another funny way, using dc, which is then not restricted to just integers:

$ dc <<< '[+]sa[z2!>az2!>b]sb1 2 3 4 5 6 6 5 4 3 2 1lbxp'
42

This wonderful line adds all the numbers. Neat, eh?

If your numbers are in an array array:

$ array=( 1 2 3 4 5 6 6 5 4 3 2 1 )
$ dc <<< '[+]sa[z2!>az2!>b]sb'"${array[*]}lbxp"
42

In fact there's a catch with negative numbers. The number '-42' should be given to dc as _42, so:

$ array=( -1.75 -2.75 -3.75 -4.75 -5.75 -6.75 -7.75 -8.75 )
$ dc <<< '[+]sa[z2!>az2!>b]sb'"${array[*]//-/_}lbxp"
-42.00

will do.

Pro: Works with floating points.

Con: Uses an external process (but there's no choice if you want to do non-integer arithmetic — but dc is probably the lightest for this task).

Solution 3

My code (which I actually utilize) is inspired by answer of gniourf_gniourf. I personally consider this more clear to read/comprehend, and to modify. Accepts also floating points, not just integers.

Sum values in array:

arr=( 1 2 3 4 5 6 7 8 9 10 )
IFS='+' sum=$(echo "scale=1;${arr[*]}"|bc)
echo $sum # 55

With small change, you can get the average of values:

arr=( 1 2 3 4 5 6 7 8 9 10 )
IFS='+' avg=$(echo "scale=1;(${arr[*]})/${#arr[@]}"|bc)
echo $avg # 5.5

Solution 4

gniourf_gniourf's answer is excellent since it doesn't require a loop or bc. For anyone interested in a real-world example, here's a function that totals all of the CPU cores reading from /proc/cpuinfo without messing with IFS:

# Insert each processor core count integer into array
cpuarray=($(grep cores /proc/cpuinfo | awk '{print $4}'))
# Read from the array and replace the delimiter with "+"
# also insert 0 on the end of the array so the syntax is correct and not ending on a "+"
read <<< "${cpuarray[@]/%/+}0"
# Add the integers together and assign output to $corecount variable
corecount="$((REPLY))"
# Echo total core count
echo "Total cores: $corecount"

I also found the arithmetic expansion works properly when calling the array from inside the double parentheses, removing the need for the read command:

cpuarray=($(grep cores /proc/cpuinfo | awk '{print $4}'))
corecount="$((${cpuarray[@]/%/+}0))"
echo "Total cores: $corecount"

Generic:

array=( 1 2 3 4 5 )
sum="$((${array[@]/%/+}0))"
echo "Total: $sum"

Solution 5

I'm a fan of brevity, so this is what I tend to use:

IFS="+";bc<<<"${array[*]}"

It essentially just lists the data of the array and passes it into BC which evaluates it. The "IFS" is the internal field separate, it essentially specifies how to separate arrays, and we said to separate them with plus signs, that means when we pass it into BC, it receives a list of numbers separated by plus signs, so naturally it adds them together.

Share:
45,243
BobbyT28
Author by

BobbyT28

IT Student Studying at FIU in Miami............ Code is not easy for me!!!!!!!!!

Updated on July 09, 2022

Comments

  • BobbyT28
    BobbyT28 almost 2 years

    I am trying to add the elements of an array that is defined by user input from the read -a command. How can I do that?