-1

I have a script where the user can add as many arguments as he would like (numbers).

The script will sum all the numbers beside the last number - The last number (argument) is the number that I need to divide by

For example:

./test.sh 2 2 6 5

This will sum the first 3 numbers (2+2+6) and divide the answer by 5 (the last argument)

  1. How can I use the last argument? Echo ????
  2. How can I move loop the first arguments besides the last one – I would like that all 3 arguments will be added to an array and I can loop it
  3. Please note that the number of arguments can be changed
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
dzbeda
  • 173
  • 2
  • 9

3 Answers3

0

Shortly (with bashisms)

As this question is tagged and :

Here is a small and efficient script:

#!/bin/bash

addVals=${*: 1 : $# - 1}
declare -i intResult=" ( ${addVals// /+} ) / ${@: -1} "
echo $intResult

But there's no loop...

Long answer

How can I use the last argument? Echo ????

You could make your tries in command line:

set -- 2 2 6 5

Then

echo $@
2 2 6 5

echo ${*: 3}
6 5

echo ${*: -1} 
5

echo ${*: 1 : -1} 
bash:  -1: substring expression < 0

echo $#  
4
echo ${*: 1 : $# -1}
2 2 6

Ok, then

someVar=${*: 1 : $# -1}
echo ${someVar// /:SpaceReplacment:}
2:SpaceReplacment:2:SpaceReplacment:6

so

declare -i result
result=" ( ${someVar// /+} ) / ${*: -1} "
echo $result
2

How can I move loop the first arguments besides the last one – I would like that all 3 arguments will be added to an array and I can loop it

Still forward, under command line...

someArray=("${@: 1: $# -1 }")

Use declare -p to show $someArray's content:

declare -p someArray
declare -a someArray=([0]="2" [1]="2" [2]="6")

Then

declare -i mySum=0
for i in "${someArray[@]}";do
    mySum+=i
done
echo $mySum
10

echo $(( mySum / ${*: -1} ))
2

Please note that the number of arguments can be changed

Please note:

  • Using double quotes allow processing of strings containing spaces:

    set -- foo bar 'foo bar baz'
    echo ${2}
    bar
    echo ${*: $# }
    foo bar baz
    
  • Difference betweeen use of "$@" (array to array) and "$*" (array to string)

    set -- foo bar 'foo bar' 'foo bar baz'
    

    If I take 3 first elements:

    someArray=("${@: 1: $# -1 }")
    declare -p someArray
    declare -a someArray=([0]="foo" [1]="bar" [2]="foo bar")
    

    But

    someArray=("${*: 1: $# -1 }")
    declare -p someArray
    declare -a someArray=([0]="foo bar foo bar")
    
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
0

How can I use the last argument? Echo ????

Granting $# > 0, you can use "${!#}".

How can I move loop the first arguments besides the last one – I would like that all 3 arguments will be added to an array and I can loop it

Again granting $# > 0, you can refer to "${@:1:$# - 1}".

Read the Arrays section in the bash manual to know how to properly expand arrays.

I also recommend learning how quoting works and knowing the dangers of unwanted word splitting and globbing.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
0

There are about a thousand ways of doing this. As you would like to make use of integer arithmetic, you can do the following in bash

A short semi-cryptic version would be:

IFS=+
echo $(( ( ${*} - ${#:-1} ) / ${#:-1} ))

Here we make use of the difference between "${*}" and "${#}" to perform the sum by setting IFS=+ (See What is the difference between "$@" and "$*" in Bash?)

A long classic approach would be:

for i in "$@"; do ((s+=i)); done
echo $(( (s-${@:-1})/${@:-1} ))

It's easier to sum all terms and subtract the last term afterwards

kvantour
  • 25,269
  • 4
  • 47
  • 72