Does anyone know of an elegant way to combine two associative arrays in bash
just like you would a normal array? Here's what I'm talking about:
In bash you can combine two normal arrays as follows:
declare -ar array1=( 5 10 15 )
declare -ar array2=( 20 25 30 )
declare -ar array_both=( ${array1[@]} ${array2[@]} )
for item in ${array_both[@]}; do
echo "Item: ${item}"
done
I want to do the same thing with two associative arrays, but the following code does not work:
declare -Ar array1=( [5]=true [10]=true [15]=true )
declare -Ar array2=( [20]=true [25]=true [30]=true )
declare -Ar array_both=( ${array1[@]} ${array2[@]} )
for key in ${!array_both[@]}; do
echo "array_both[${key}]=${array_both[${key}]}"
done
It gives the following error:
./associative_arrays.sh: line 3: array_both: true: must use subscript when assigning associative array
The following is a work-around I came up with:
declare -Ar array1=( [5]=true [10]=true [15]=true )
declare -Ar array2=( [20]=true [25]=true [30]=true )
declare -A array_both=()
for key in ${!array1[@]}; do
array_both+=( [${key}]=${array1[${key}]} )
done
for key in ${!array2[@]}; do
array_both+=( [${key}]=${array2[${key}]} )
done
declare -r array_both
for key in ${!array_both[@]}; do
echo "array_both[${key}]=${array_both[${key}]}"
done
But I was hoping that I'm actually missing some grammar that will allow the one-liner assignment as shown in the non-working example.
Thanks!
I don't have a one-liner either but here is a different 'workaround' that someone might like using string convertion. It's 4 lines, so I'm only 3 semi-colons from the answer you wanted!
declare -Ar array1=( [5]=true [10]=true [15]=true )
declare -Ar array2=( [20]=true [25]=true [30]=true )
# convert associative arrays to string
a1="$(declare -p array1)"
a2="$(declare -p array2)"
#combine the two strings trimming where necessary
array_both_string="${a1:0:${#a1}-3} ${a2:21}"
# create new associative array from string
eval "declare -A array_both="${array_both_string#*=}
# show array definition
for key in ${!array_both[@]}; do
echo "array_both[${key}]=${array_both[${key}]}"
done
this works with bash > 4.3
print_associative_array() {
# declare a local **reference variable** (hence `-n`) named `array_reference`
# which is a reference to the value stored in the first parameter
# passed in
echo "printing associative array: $1"
local -n map_ref="$1"
# print the array by iterating through all of the keys now
for key in "${!map_ref[@]}"; do
value="${map_ref["$key"]}"
echo " $key: $value"
done
}
merge_associative_array() {
# declare a local **reference variable** (hence `-n`) named `array_reference`
# which is a reference to the value stored in the first parameter
# passed in
echo "merging associative arrays: $1 <--- $2"
local -n map_ref="$1"
local -n map_ref2="$2"
# setting the value of keys in the second array, to the value of the same key in the first array
for key in "${!map_ref2[@]}"; do
value="${map_ref2["$key"]}"
echo " $key: $value"
map_ref["$key"]="$value"
done
print_associative_array "$1"
}
declare -A optionsA
optionsA=( ["--hello"]="HELLO" ["--world"]="WORLD" )
declare -A optionsB
optionsB=( ["--key1"]="keyval" ["--world"]="WORLD2" ["--new-key"]="xyz" )
merge_associative_array "optionsA" "optionsB"
I was inspired by answer of @Gabriel Staples
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