how to pass array into function and updates to array are reflected outsite function
Matthew Barrera
I am trying to pass a array into a function and whatever changes made to the array is reflected outside the function
function update_array()
{ ${1[0]}="abc" # trying to change zero-index array to "abc" , # bad substitution error
}
foo=(foo bar)
update_array foo[@]
for i in ${foo[@]} do echo "$i" # currently changes are not reflected outside the function doneMy questions are
1) How do i access the index array eg: zero index array , in the function , what is the syntax for it
2) How do i make changes to this index array so that the changes are reflected outsite the function also
3 Answers
Several problems, in logical order of fixing:
- Style (pet peeve)
With your
${...}statement inupdate_array(), the${..}syntax to use a variable, not define it.Example:
foo[0]=abc # assigns 'abc' to foo[0]Working around that the array name is stored in a variable.
Not working:
$1[0]=abcWorking:
declare -g "$1[0]=abc" # -g arg is for a global variablePassing an argument to
update_array()should pass the variable name (fooin this case), not the contents of the array.foo[@]is nothing special, it is a completely normal string (in Bash).Variable expansion with
${foo[@]}should be double-quoted.
Working version of the code is below:
update_array() { declare -g "$1[0]=abc"
}
foo=(foo bar)
update_array foo
for i in "${foo[@]}"; do echo "$i"
done
## Following line added by me for further clarification
declare -p foowhich prints, correctly:
abc
bar
declare -a foo='([0]="abc" [1]="bar")' 3 Declaration of variables might not be necessary in Bash.1 Yes you can use declare/typeset for more control over your bash variables. So I reckon you don't have to create a function just for the purpose of declaring a new array.
This script below demonstrates a direct defining of array:
#!/bin/bash
function define_array_elements() {
# You can note the array elements being defined directly, without a prior
# definition of the variable.
for i in {1..10}; do var_name[$i]="Field $i of the list"
done
}
define_array_elements > /dev/null
for i in {1..10}; do echo "Field $i is: ${var_name[$i]}"
done(An example borrowed from How to declare an array but not define it? with just a little modification.)
1Short answer is: you cannot. Bash does not have a way to pass variables by reference, so there's no generic way of doing it; you're left with (ugly) hacks including indirection and/or eval.
The upcoming bash 4.3 will introduce nameref variables, which allow you to pass variables by reference, but even this feature falls short since you still risk name collition.
# example of passing variables by reference in bash 4.3
update_array() { declare -n array=$1 array[0]=abc
}
foo=( foo bar )
update_array foo
printf '<%s>\n' "${foo[@]}" # outputs <abc> and <bar>In that example, if the array was named array instead of foo, it would fail since declare -n array=array is an error (declare: array: nameref variable self references not allowed).
See for other hacks.