I have a function that creates an array and I want to return the array to the caller:
create_array() { local my_list=("a", "b", "c") echo "${my_list[@]}" } my_algorithm() { local result=$(create_array) }
With this, I only get an expanded string. How can I "return" my_list without using anything global?
Print Bash Array We can use the keyword 'declare' with a '-p' option to print all the elements of a Bash Array with all the indexes and details. The syntax to print the Bash Array can be defined as: declare -p ARRAY_NAME.
bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.
Yes, bash 's return can only return numbers, and only integers between 0 and 255.
With Bash version 4.3 and above, you can make use of a nameref so that the caller can pass in the array name and the callee can use a nameref to populate the named array, indirectly.
#!/usr/bin/env bash create_array() { local -n arr=$1 # use nameref for indirection arr=(one "two three" four) } use_array() { local my_array create_array my_array # call function to populate the array echo "inside use_array" declare -p my_array # test the array } use_array # call the main function
Produces the output:
inside use_array declare -a my_array=([0]="one" [1]="two three" [2]="four")
You could make the function update an existing array as well:
update_array() { local -n arr=$1 # use nameref for indirection arr+=("two three" four) # update the array } use_array() { local my_array=(one) update_array my_array # call function to update the array }
This is a more elegant and efficient approach since we don't need command substitution $()
to grab the standard output of the function being called. It also helps if the function were to return more than one output - we can simply use as many namerefs as the number of outputs.
Here is what the Bash Manual says about nameref:
A variable can be assigned the nameref attribute using the -n option to the declare or local builtin commands (see Bash Builtins) to create a nameref, or a reference to another variable. This allows variables to be manipulated indirectly. Whenever the nameref variable is referenced, assigned to, unset, or has its attributes modified (other than using or changing the nameref attribute itself), the operation is actually performed on the variable specified by the nameref variable’s value. A nameref is commonly used within shell functions to refer to a variable whose name is passed as an argument to the function. For instance, if a variable name is passed to a shell function as its first argument, running
declare -n ref=$1 inside the function creates a nameref variable ref whose value is the variable name passed as the first argument. References and assignments to ref, and changes to its attributes, are treated as references, assignments, and attribute modifications to the variable whose name was passed as $1.
What's wrong with globals?
Returning arrays is really not practical. There are lots of pitfalls.
That said, here's one technique that works if it's OK that the variable have the same name:
$ f () { local a; a=(abc 'def ghi' jkl); declare -p a; } $ g () { local a; eval $(f); declare -p a; } $ f; declare -p a; echo; g; declare -p a declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")' -bash: declare: a: not found declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")' -bash: declare: a: not found
The declare -p
commands (except for the one in f()
are used to display the state of the array for demonstration purposes. In f()
it's used as the mechanism to return the array.
If you need the array to have a different name, you can do something like this:
$ g () { local b r; r=$(f); r="declare -a b=${r#*=}"; eval "$r"; declare -p a; declare -p b; } $ f; declare -p a; echo; g; declare -p a declare -a a='([0]="abc" [1]="def ghi" [2]="jkl")' -bash: declare: a: not found -bash: declare: a: not found declare -a b='([0]="abc" [1]="def ghi" [2]="jkl")' -bash: declare: a: not found
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With