1

If I have a bash function with two or more params, and the first is an array, how can I access the second param?

It's the same as this question but the non-array param is the first argument there, while mine is not (so it does not answer my question).

function getParam() {
   arr=("$@")
   for i in "${arr[@]}";
   do
      echo $i #works - print array item
   done

   var=$2
   echo $var #not working - returns two; I want 3
}

array=('one' 'two' 'three')

getParam "${array[@]}" 3
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Mote Zart
  • 861
  • 3
  • 17
  • 33
  • 5
    That *doesn't* pass the array as the first parameter. It passes *each element in the array* as a separate parameter -- which is all you *can* do, since arguments are by nature strings. – Charles Duffy Feb 21 '19 at 20:35
  • ...so the easy answer is to change your calling convention to put the non-array argument *first*, as in the linked answer. – Charles Duffy Feb 21 '19 at 20:36
  • ...and the less-easy answer is to pass the array by name rather than by value, for which we have plenty of duplicates already in the knowledge base. – Charles Duffy Feb 21 '19 at 20:36
  • But I don't have access to change the order. – Mote Zart Feb 21 '19 at 20:37
  • If you can't change the caller (and can only change the function definition), then you can't change to pass-by-name either, so what you're asking us to do is take everything but the last entry in your argument list into an array, and treat the last argument as a separate value. That's doable, and I'd have to look to see if there are duplicates for it. – Charles Duffy Feb 21 '19 at 20:38
  • Note that `bash` doesn't have array *values* at all. Setting the array attribute on a *name* provides additional syntax for indexing the *simulates* an array value. Note that `$array` and `${array[0]}` expand to exactly the same thing, whether or not the array attribute is set on the name `array`. – chepner Feb 21 '19 at 20:39
  • 1
    BTW, see [BashPitfalls #14](http://mywiki.wooledge.org/BashPitfalls#echo_.24foo) re: `echo $i` and `echo $var`. – Charles Duffy Feb 21 '19 at 20:42

2 Answers2

3

You can't pass arrays to functions in bash. You can only pass strings.

Any arrays passed with "${array[@]}" will expand to multiple parameters (similar to the "splat" operator in some languages). This:

getParam "${array[@]}" 3

Is therefore equivalent to this:

getParam "one" "two" "three" 3

Explaining why $2 is two

Instead, you can:

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • 1
    [remove the last element from an array](https://stackoverflow.com/questions/8247433/remove-the-last-element-from-an-array) might be an additional element of the "get the last parameter" solution. – Charles Duffy Feb 21 '19 at 20:41
  • I think getting the last param is going to be the way to go. – Mote Zart Feb 21 '19 at 22:06
0

What you can do here is use a couple of tricky parameter expansions:

getparams() {
    local ary=( "${@:1:$#-1}" )
    local last=${!#}
    declare -p ary last
}

getparams "a b" "c d" 10
declare -a ary='([0]="a b" [1]="c d")'
declare -- last="10"

ary is taking a slice of the positional parameters, starting with index 1 and taking ($# - 1) = (3 - 1) = 2 elements.
last is variable indirection: $# here is 3, so ${!#} is equivalent to $3.

Ref: Shell Parameter Expansion

glenn jackman
  • 238,783
  • 38
  • 220
  • 352