13

In below function with 9 arguments:

SUM() { 
    echo "The sum is $(($1+$2+$3+$4+$5+$6+$7+$8+$9))"
}

I want to make the second arguments to the next(3..9) become a optional arguments.

When I call the function with 2 arguments I get error:

SUM 3 8
bash: 3+8+++++++: syntax error: operand expected (error token is "+")

Note BOLD: first argument and second argument are force arguments and not optional for function. I only want second arguments to the next is optional and when I call the function less than 2 args the function must return no result.

22

If you won't pass arguments with spaces:

sum() {  
[[ -n $2 ]] && echo $(( $(tr ' ' '+' <<<"$@") ))
}

Effect:

$ sum 1 2 3
6

Explanation:

  1. <<<"some string" feeds in only "some string" as the input. Think of it as shorthand for echo "some string" |. It is called a Here String.
  2. "$@" expands into all the positional parameters, separated by spaces. It is equivalent to "$1 $2 ...".
  3. Hence, tr ' ' '+' <<<"$@" outputs "$1+$2+$3...", which is evaluated by the outer $(( )).
  4. [[ -n $2 ]] tests if the second parameter is non-empty. You could replace [[ -n $2 ]] && with [[ -z $2 ]] ||.

Another way:

sum() {
[[ -n $2 ]] && (IFS=+; echo $(( $* )))
}

Explanation:

  1. $* is just like $@, except that the parameters are not separated by spaces, but by the first character of the Internal Field Separator (IFS). With IFS=+, it expands to "$1+$2+...". See What is the difference between $* and $@?
  2. We set IFS in a subshell (note the surrounding parentheses) so that the main shell isn't affected. IFS is, by default: \t\n (space, tab, newline). This is an alternative to using local variables.

Now to answer your question:

You can use a default value for any variable or parameter. Either:

SUM() { 
 echo "The sum is $(($1+$2+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))" || false
}

Or:

SUM() { 
 echo "The sum is $(($1+$2+${3:=0}+${4:=0}+${5:=0}+${6:=0}+${7:=0}+${8:=0}+${9:=0}))" || false
}
  • 6
    Nifty! I know comments aren't meant for gratuitous compliments and thanks, but this solution is just ... wicked! :-) – zwets Sep 10 '14 at 8:59
17

Have a look at the shift operator. It will shift arguments 2 and onward to positions 1 and onward, discarding argument 1.

sum () {
    local total=0;
    while [ $# -gt 0 ]; do
        total=$(($total + $1))
        shift
    done
    echo $total
}
4

You could use a recursive definition which terminates when sum is invoked without arguments. We make use of the fact that test without arguments evaluates to false.

sum () {
    test $1 && echo $(( $1 + $(shift; sum $@) )) || echo 0
}
3

Try this:

SUM () {
 [ $# -lt "2" ] && return 1
 for par in $@; do
   local sum=`expr $sum + $par`
 done
 echo $sum
 return 0
}

SUM 3 4 5
SUM 3 4 5 1 1 1 1 2 3 4 5

This will output 12 and 30.

$@ refers to parameter, $# returns the number of parameter, in this case 3 or 11.

Tested on linux redhat 4

2

You could just use a little loop:

sum(){
    t=0;
    for i in "$@"; do t=$((t + i )); done
    echo $t;
}

Personally though, I'd just use perl or awk instead:

sum(){
 echo "$@" | perl -lane '$s+=$_ for @F; print $s'
}

or

sum(){
 echo "$@" | awk '{for(i=1; i<=NF; i++){k+=$i} print k}'
}
2

Use 0 as default values for $1 to $9:

SUM() { 
    echo "The sum is $((${1:-0}+${2:-0}+${3:-0}+${4:-0}+${5:-0}+${6:-0}+${7:-0}+${8:-0}+${9:-0}))"
}

From man bash:

${parameter:-word}
    Use Default Values. If parameter is unset or null, the expansion
    of word is substituted. Otherwise, the value of parameter is
    substituted.

Examples:

$ SUM

The sum is 0

$ SUM 1 2 

The sum is 3

$ SUM 1 1 1 1 1 1 1 1 1 

The sum is 9


Same output with awk:

SUM() {
  echo -e ${@/%/\\n} | awk '{s+=$1} END {print "The sum is " s}'
}
1

It's also my own solution I tried it and found:

SUM() { 
    echo "The sum is $(($1+$2+$[$3]+$[$4]+$[$5]+$[$6]+$[$7]+$[$8]+$[$9]))"
 }

$ SUM 4 6 5
The sum is 15

But @muru's answer is good.

  • +1: Interesting usage of two arithmetic expansions to evaluate empty parameters to zero. – muru Sep 10 '14 at 9:29
  • 1
    @muru thanks, but in this case my answer we don't use more than 9 arguments and we have to use group of arguments to pass more than 9. thank you for your answer that's perfect. – αғsнιη Sep 10 '14 at 9:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.