Referencing bash array variables from another array
Bash 4.3 and later supports "name references", or namerefs (a similar concept exists in ksh93
, but the scoping is annoyingly different):
#!/bin/bash
array1=('array1string1' 'array1string2')
array2=('array2string1' 'array2string2')
array_names=('array1' 'array2')
for a in "${array_names[@]}"; do
declare -n arr="$a"
for b in "${arr[@]}"; do
echo "$b"
done
done
The variable arr
is a nameref that acts like an alias for the named variable (the variable with name $a
in this example).
Without namerefs, in earlier Bash versions, one solution would be to create a new array that contains all the elements from the other arrays:
all=( "${array1[@]}" "${array2[@]}" )
... a bit like the array_names
array in the question but with the contents of all arrays, and then iterate over "${all[@]}"
.
It's also possible to use eval
, but the resulting code looks astoundingly awful.
See glenn jackman's answer for a variation with variable indirection (introduced in its current form with Bash version 2).
@Kusalananda has the best answer for recent versions of bash. For earlier versions, you can use an indirect variable:
for a in ${array_names[@]}; do
tmp="${a}[@]"
for b in "${!tmp}"; do echo "$b"; done # or: printf "%s\n" "${!tmp}"
done
See the 4th paragraph of https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion