Passing arrays as parameters in bash
You can pass multiple arrays as arguments using something like this:
takes_ary_as_arg(){ declare -a argAry1=("${!1}") echo "${argAry1[@]}" declare -a argAry2=("${!2}") echo "${argAry2[@]}"}try_with_local_arys(){ # array variables could have local scope local descTable=( "sli4-iread" "sli4-iwrite" "sli3-iread" "sli3-iwrite" ) local optsTable=( "--msix --iread" "--msix --iwrite" "--msi --iread" "--msi --iwrite" ) takes_ary_as_arg descTable[@] optsTable[@]}try_with_local_arys
will echo:
sli4-iread sli4-iwrite sli3-iread sli3-iwrite --msix --iread --msix --iwrite --msi --iread --msi --iwrite
Edit/notes: (from comments below)
descTable
andoptsTable
are passed as names and are expanded in the function. Thus no$
is needed when given as parameters.- Note that this still works even with
descTable
etc being defined withlocal
, because locals are visible to the functions they call. - The
!
in${!1}
expands the arg 1 variable. declare -a
just makes the indexed array explicit, it is not strictly necessary.
Note: This is the somewhat crude solution I posted myself, after not finding an answer here on Stack Overflow. It allows for only one array being passed, and it being the last element of the parameter list. Actually, it is not passing the array at all, but a list of its elements, which are re-assembled into an array by called_function(), but it worked for me. Somewhat later Ken posted his solution, but I kept mine here for "historic" reference.
calling_function(){ variable="a" array=( "x", "y", "z" ) called_function "${variable}" "${array[@]}"}called_function(){ local_variable="${1}" shift local_array=("${@}")}
Commenting on Ken Bertelson solution and answering Jan Hettich:
How it works
the takes_ary_as_arg descTable[@] optsTable[@]
line in try_with_local_arys()
function sends:
- This is actually creates a copy of the
descTable
andoptsTable
arrays which are accessible to thetakes_ary_as_arg
function. takes_ary_as_arg()
function receivesdescTable[@]
andoptsTable[@]
as strings, that means$1 == descTable[@]
and$2 == optsTable[@]
.in the beginning of
takes_ary_as_arg()
function it uses${!parameter}
syntax, which is called indirect reference or sometimes double referenced, this means that instead of using$1
's value, we use the value of the expanded value of$1
, example:baba=boobavariable=babaecho ${variable} # babaecho ${!variable} # booba
likewise for
$2
.- putting this in
argAry1=("${!1}")
createsargAry1
as an array (the brackets following=
) with the expandeddescTable[@]
, just like writing thereargAry1=("${descTable[@]}")
directly. thedeclare
there is not required.
N.B.: It is worth mentioning that array initialization using this bracket form initializes the new array according to the IFS
or Internal Field Separator which is by default tab, newline and space. in that case, since it used [@]
notation each element is seen by itself as if he was quoted (contrary to [*]
).
My reservation with it
In BASH
, local variable scope is the current function and every child function called from it, this translates to the fact that takes_ary_as_arg()
function "sees" those descTable[@]
and optsTable[@]
arrays, thus it is working (see above explanation).
Being that case, why not directly look at those variables themselves? It is just like writing there:
argAry1=("${descTable[@]}")
See above explanation, which just copies descTable[@]
array's values according to the current IFS
.
In summary
This is passing, in essence, nothing by value - as usual.
I also want to emphasize Dennis Williamson comment above: sparse arrays (arrays without all the keys defines - with "holes" in them) will not work as expected - we would loose the keys and "condense" the array.
That being said, I do see the value for generalization, functions thus can get the arrays (or copies) without knowing the names:
- for ~"copies": this technique is good enough, just need to keep aware, that the indices (keys) are gone.
for real copies:we can use an eval for the keys, for example:
eval local keys=(\${!$1})
and then a loop using them to create a copy.Note: here !
is not used it's previous indirect/double evaluation, but rather in array context it returns the array indices (keys).
- and, of course, if we were to pass
descTable
andoptsTable
strings (without[@]
), we could use the array itself (as in by reference) witheval
. for a generic function that accepts arrays.