Two ways to pass associative arrays as parameters in bash
For regular bash indexed arrays, see my two other answers here (by reference) and here (by value). For printing arrays by value or reference, see my answer here.
1. Manual passing (via serialization/deserialization) of the associative array
Here's another way: you can manually serialize the associative array as you pass it to a function, then deserialize it back into a new associative array inside the function:
Here's a full, runnable example from my eRCaGuy_hello_world repo:
array_pass_as_bash_parameter_2_associative.sh:
# Print an associative array using manual serialization/deserialization
# Usage:
# # General form:
# print_associative_array array_length array_keys array_values
#
# # Example:
# # length indices (keys) values
# print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
print_associative_array() {
i=1
# read 1st argument, the array length
array_len="${@:$i:1}"
((i++))
# read all key:value pairs into a new associative array
declare -A array
for (( i_key="$i"; i_key<$(($i + "$array_len")); i_key++ )); do
i_value=$(($i_key + $array_len))
key="${@:$i_key:1}"
value="${@:$i_value:1}"
array["$key"]="$value"
done
# print the array by iterating through all of the keys now
for key in "${!array[@]}"; do
value="${array["$key"]}"
echo " $key: $value"
done
}
# Let's create and load up an associative array and print it
declare -A array1
array1["a"]="cat"
array1["b"]="dog"
array1["c"]="mouse"
# length indices (keys) values
print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
Sample output:
a: cat
b: dog
c: mouse
Explanation:
For a given function named print_associative_array
, here is the general form:
# general form
print_associative_array array_length array_keys array_values
For an array named array1
, here is how to obtain the array length, indices (keys), and values:
- array length:
"${#array1[@]}"
- all of the array indices (keys in this case, since it's an associative array):
"${!array1[@]}"
- all of the array values:
"${array1[@]}"
So, an example call to print_associative_array
would look like this:
# example call
# length indices (keys) values
print_associative_array "${#array1[@]}" "${!array1[@]}" "${array1[@]}"
Putting the length of the array first is essential, as it allows us to parse the incoming serialized array as it arrives into the print_associative_array
function inside the magic @
array of all incoming arguments.
To parse the @
array, we'll use array slicing, which is described as follows (this snippet is copy-pasted from my answer here):
# array slicing basic format 1: grab a certain length starting at a certain
# index
echo "${@:2:5}"
# │ │
# │ └────> slice length
# └──────> slice starting index (zero-based)
2. [Better technique than above!] Pass the array by reference
...as @Todd Lehman explains in his answer here
# Print an associative array by passing the array by reference
# Usage:
# # General form:
# print_associative_array2 array
# # Example
# print_associative_array2 array1
print_associative_array2() {
# declare a local **reference variable** (hence `-n`) named `array_reference`
# which is a reference to the value stored in the first parameter
# passed in
local -n array_reference="$1"
# print the array by iterating through all of the keys now
for key in "${!array_reference[@]}"; do
value="${array_reference["$key"]}"
echo " $key: $value"
done
}
echo 'print_associative_array2 array1'
print_associative_array2 array1
echo ""
echo "OR (same thing--quotes don't matter in this case):"
echo 'print_associative_array2 "array1"'
print_associative_array2 "array1"
Sample output:
print_associative_array2 array1
a: cat
b: dog
c: mouse
OR (same thing--quotes don't matter in this case):
print_associative_array2 "array1"
a: cat
b: dog
c: mouse
See also:
- [my answer] a more-extensive demo of me serializing/deserializing a regular "indexed" bash array in order to pass one or more of them as parameters to a function: Passing arrays as parameters in bash
- [my answer] a demo of me passing a regular "indexed" bash array by reference: Passing arrays as parameters in bash
- [my answer] array slicing: Unix & Linux: Bash: slice of positional parameters
- [my question] Why do the
man bash
pages state the declare
and local
-n
attribute "cannot be applied to array variables", and yet it can?
- [my answer] How to manually pass an associative array to and from a subprocess in Bash