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?
9 Answers
read -a array
tot=0
for i in ${array[@]}; do
let tot+=$i
done
echo "Total: $tot"

- 94,503
- 21
- 155
- 181
-
what is the function of "let"? – BobbyT28 Nov 29 '12 at 22:18
-
1adds each item to the total. – perreal Nov 29 '12 at 22:21
-
can you do this using "expr"? – BobbyT28 Nov 29 '12 at 22:28
-
@BobbyT28, but you don't need to call out to an external program when the shell has the ability to do arithmetic. – glenn jackman Nov 30 '12 at 01:12
-
Does `let` work with decimals? I had to use `total=$(echo "$total + $i" | bc -l)` – userABC123 Nov 03 '15 at 21:32
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).

- 1
- 1

- 44,650
- 9
- 93
- 104
-
3
-
does not work on natural numbers: $ echo "${arrr[*]}" 2 1 34 3 2 $ IFS=+ read <<< "${arrr[*]}" then no + is provided: $ echo $REPLY 2 1 34 3 2 – Chris Oct 03 '19 at 16:45
-
The (very smart) first solution does create a subshell because command substitution (`$(...)`) in Bash _always_ creates a subshell. See [mklement0's answer](https://stackoverflow.com/a/21338131/4154375) to [When does command substitution spawn more subshells than the same commands in isolation?](https://stackoverflow.com/q/21331042/4154375). – pjh Nov 08 '19 at 19:03
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
-
-
1FYI this can have consequences in other parts of a script when IFS is defined – Mike Q Jul 18 '19 at 16:15
-
1Yes, @MikeQ. The IFS must be moved inside the subshell to prevent contaminating the running shell. `arr=( 1 2 3 4 5 6 7 8 9 10 ); echo $(IFS='+'; bc<<<"scale=1;(${arr[*]})/${#arr[@]}")` Also, you can use a "Here String" instead of echo to save 1 process. – Bruno Bronosky Feb 08 '20 at 02:02
-
1@BrunoBronosky, then one could backup and restore IFS variable after the operation etc. .. – Mike Q Feb 08 '20 at 02:28
-
1@MikeQ The way IFS is (re-)defined here, it will only be in effect for that single command line. Backing up and restoring IFS is not necessary here – SpinUp __ A Davis Jul 24 '22 at 04:47
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"

- 159
- 2
- 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.

- 171
- 1
- 6
Another dc
& bash
method:
arr=(1 3.88 7.1 -1)
dc -e "0 ${arr[*]/-/_} ${arr[*]/*/+} p"
Output:
10.98
The above runs the expression 0 1 3.88 7.1 _1 + + + + p
with dc
. Note the dummy value 0
because there's one too many +
s, and also note the usual negative number prefix -
must be changed to _
in dc
.

- 7,973
- 2
- 29
- 50
arr=(1 2 3) //or use `read` to fill the array
echo Sum of array elements: $(( ${arr[@]/%/ +} 0))
Sum of array elements: 6
Explanation:
"${arr[@]/%/ +}"
will return1 + 2 + 3 +
- By adding additional zero at the end we will get
1 + 2 + 3 + 0
- By wrapping this string with BASH's math operation like this
$(( "${arr[@]/%/ +} 0"))
, it will return the sum instead
This could be used for other math operations.
- For subtracting just use
-
instead - For multiplication use
*
and1
instead of0
Can be used with logic operators too.
BOOL AND EXAMPLE - check if all items are true (1)
arr=(1 0 1)
if [[ $((${arr[@]/%/ &} 1)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
This will print: no
BOOL OR EXAMPLE - check if any item is true (1)
arr=(1 0 0)
if [[ $((${arr[@]/%/ |} 0)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
This will print: yes

- 4,323
- 1
- 21
- 22
I find this very simple using an increasing variable:
result2=0
for i in ${lineCoffset[@]};
do
result2=$((result2+i))
done
echo $result2

- 46,058
- 19
- 106
- 116

- 51
- 2
A simple way
function arraySum
{
sum=0
for i in ${a[@]};
do
sum=`expr $sum + $i`
done
echo $sum
}
a=(7 2 3 9)
echo -n "Sum is = "
arraySum ${a[@]}

- 3,588
- 2
- 39
- 40