As mentioned earlier, bash arrays are one-dimensional. Over the years, people have come up with ways to βfakeβ multidimensional arrays.
The two methods I used were to maintain an array of array descriptions or an array of pointers to other arrays. I will answer first; the latter should be obvious if you want to explore on your own.
Here is a minimal example of the contents of an array that is used to populate variables:
#!/usr/bin/env bash declare -A a=( [b]='([0]="one" [1]="two")' [c]='([0]="three" [1]="four")' ) declare -pa for key in ${!a[@]}; do declare -a $key="${a[$key]}" declare -p $key done
It produces:
declare -A a=([b]="([0]=\"one\" [1]=\"two\")" [c]="([0]=\"three\" [1]=\"four\")" ) declare -ab=([0]="one" [1]="two") declare -ac=([0]="three" [1]="four")
The critical bit here is that you use declare to indicate the value of $key , since you cannot just say $var="value" in bash.
Of course, you do not need to specify variables for the value of $key unless you want to. Storing values ββin, for example $value , will free you from using special characters in $key .
An even simpler alternative, if it does not offend your sensitivity or limits your key names too much, is to store the entire output of the declare -p command in an array value and then eval when you need it. For instance:
declare -A a=( [b]='declare -ab=([0]="one" [1]="two")' [c]='declare -ac=([0]="three" [1]="four")' ) for key in ${!a[@]}; do eval "${a[$key]}" done
Some people don't like eval . :-) It remains, however, in your tool.
In your case, a little advice, because you did not provide the full MCVE , but here is my contrived example.
#!/usr/bin/env bash # contrived getServices function, since you didn't provide one getServices() { local -a value=() local last="${1:$((${#1}-1)):1}" # last character of $1 for n in $( seq 1 $(( $RANDOM / 8192 + 1 )) ); do value+=(${last}${n}) done declare -p value # output of this function is actual bash code. } # populate the array listService() { servicesList[$1]=$( getServices $1 ) } # Initialize this as empty to make `eval` safer declare -A servicesList=() # These services seem interesting. listService serviceA listService serviceB listService serviceC # Note that we're stepping through KEYS here, not values. for row in "${!servicesList[@]}"; do printf '"%s": ' "$row" eval "${servicesList[$row]}" # Someone is bound to complain about this. for column in "${!value[@]}"; do # Add whatever $row and $column specific code you like here. printf '%s ' "${value[$column]}" done printf "\n" done
My conclusion:
$ bash 2dimarrayexample "serviceC": C1 "serviceB": B1 B2 B3 B4 "serviceA": A1 A2
Of course, your output may be different, as getServices produces random output. :)