2

Is there a way to pass an array to a function as one of its parameters?

Currently I have

#!/bin/bash
highest_3 () {
  number_under_test=(${array[@]})
  max_of_3=0
  for ((i = 0; i<$((${#number_under_test[@]}-2)); i++ )) { 
    test=$((number_under_test[i] +
      number_under_test[i+1] +
      number_under_test[i+2]))
    if [ $test -gt $max_of_3 ]; then
      max_of_3=$((number_under_test[i]+
        number_under_test[i+1]+
        number_under_test[i+2]))
      result=$((number_under_test[i]))$((number_under_test[i+1]))$((number_under_test[i+2]))
    fi
  } 
}
array=(1 2 3 4 5 6 7 8 7 6 5 4 3 2 1)
highest_3
echo result=$result
array=(1 2 3 4 3 2 1)
highest_3
echo result=$result

which works by just setting array and using array, but is there a way to pass in the array, e.g. (1 2 3 4 5 4 3 2 1) as an actual parameter rather than just setting a (presumably global) variable?

Update: I'd like to be able to pass in other parameters beside this array

6

You can always pass the array to the function and rebuild it as an array within the function:

#!/usr/bin/env bash

foo () {
    ## Read the 1st parameter passed into the new array $_array
    _array=( "$1" )
    ## Do something with it.
    echo "Parameters passed were 1: ${_array[@]}, 2: $2 and 3: $3"

}
## define your array
array=(a 2 3 4 5 6 7 8 7 6 5 4 3 2 1)
## define two other variables
var1="foo"
var2="bar"

## Call your function
foo "$(echo ${array[@]})" $var1 $var2

The script above produces the following output:

$ a.sh
Parameters passed were 1: a 2 3 4 5 6 7 8 7 6 5 4 3 2 1, 2: foo and 3: bar
  • 1
    But the array is not the same inside of foo(). In main, your ${#array[@]} results to 15 elements, but in foo() ${#_array[@]} shows just 1 element. See also here. – Joe Sep 21 '17 at 16:36
3

You could read the arguments inside the function as an array. And then invoke the function with those arguments. Something like this worked for me.

#!/bin/bash

highest_3 () {
number_under_test=("$@")
max_of_3=0
for ((i = 0; i<$((${#number_under_test[@]}-2)); i++ )) { 
 test=$((number_under_test[i] +
  number_under_test[i+1] +
  number_under_test[i+2]))
if [ $test -gt $max_of_3 ]; then
  max_of_3=$((number_under_test[i]+
    number_under_test[i+1]+
    number_under_test[i+2]))
  result=$((number_under_test[i]))$((number_under_test[i+1]))$((number_under_test[i+2]))
fi
} 
echo $result
}

highest_3 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1

# or
array=(1 2 3 4 5 6 7 8 7 6 5 4 3 2 1)
highest_3 "${array[@]}"
  • +1 Would there also be a way to pass in other parameters? Is the only way to have their positions specified, e.g. p1 is x, p2 is y and p3-p10 are the array elements? Thx! – Michael Durrant Feb 8 '15 at 14:07
  • 1
    You could take a look at getopts - wiki.bash-hackers.org/howto/getopts_tutorial. I'll see if I can get a sample working. – rahul Feb 8 '15 at 14:16
  • @MichaelDurrant - no, when you work with an arg array you shift or otherwise iterate over it. Like fn() for arg do echo "$arg"; done; fn 1 2 3 4 – mikeserv Feb 8 '15 at 16:03
1

You can pass only strings as arguments. But you could pass the name of the array:

highest_3 () {
  arrayname="$1"
  test -z "$arrayname" && exit 1
  # this doesn't work but that is the idea: echo "${!arrayname[1]}"
  eval echo '"${'$arrayname'[1]}"'
}
  • You can do the indirect thing, but you have to store the ! in the value. – mikeserv Feb 8 '15 at 21:59

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.