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

3 Answers3

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
terdon
  • 242,166
  • 3
    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[@]}"
Hauke Laging
  • 90,279
rahul
  • 1,181
  • +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 08 '15 at 14:07
  • 1
    You could take a look at getopts - http://wiki.bash-hackers.org/howto/getopts_tutorial. I'll see if I can get a sample working. – rahul Feb 08 '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 08 '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]}"'
}
Hauke Laging
  • 90,279