Your first script is looping through $@, if you want to add an operand, you can save the first argument (op=$1) and then use shift.
from man bash:
shift [n]
The positional parameters from n+1 ... are renamed to $1 .... Parameters represented by the numbers $# down to $#-n+1 are unset. n must be a non-negative number less than or equal to $#. If n is 0, no parameters are changed. If n is not given, it is assumed to be 1. If n is greater than $#, the positional parameters are not changed. The return status is greater than zero if n is greater than $# or less than zero; otherwise 0.
Initialize $result with the first argument, then use shift again.
Also, make sure to quote $@ when running the loop (read here).
#!/bin/bash
op=$1
shift
result=$1
shift
for var in "$@"; do
result=$(( result $op var ))
done
echo "$result"
You could also do the shift in one step:
op=$1
result=$2
shift 2
Run test.sh + 1 2 3 or test.sh '*' 1 2 3 ...
('*' must be quoted, to not expand to filenames).
However, I would rather use bc and $IFS instead of a loop and $(( ... ))) for this:
#!/bin/bash
OLDIFS="$IFS"
IFS=$1
shift
bc <<< "scale=5; $*"
IFS=$OLDIFS
The reason this works is, that "$*" expands to "1${IFS}2${IFS}3". With ${IFS} set as the operator with IFS=$1, e.g. +, we get bc <<< "1+2+3"See also:
"$*"expands to a single word"$1c$2c...". Usuallycis a space, but it's actually the first character ofIFS, so it can be anything you choose.