It's hacky, but you can serialize an array with declare -p (typeset -p also works). Using that strategy, you can make an array of serialized arrays in bash, and then eval them. Notice that we have to use quoting if we care about empty strings as values:
# multidimensional array of red, yellow, and green things
# serialized with `declare -p`
# red, yellow, green things
declare -a color_table=(
"$(inner_row=(stop caution go); declare -p inner_row)"
"$(inner_row=(rose tulip clover); declare -p inner_row)"
"$(inner_row=(strawberry banana grape); declare -p inner_row)"
)
And here's how you can use that multidimensional array:
# using eval, we deserialize the inner_row variable as we loop
echo "=== table ==="
printf '%s\n' "${color_table[@]}"
echo "=== rows ==="
for row in "${color_table[@]}"; do
eval $row
echo "red thing: ${inner_row[0]}"
echo "yellow thing: ${inner_row[1]}"
echo "green thing: ${inner_row[2]}"
done
And the output is:
=== table ===
declare -a inner_row=([0]="stop" [1]="caution" [2]="go")
declare -a inner_row=([0]="rose" [1]="tulip" [2]="clover")
declare -a inner_row=([0]="strawberry" [1]="banana" [2]="grape")
=== rows ===
red thing: stop
yellow thing: caution
green thing: go
red thing: rose
yellow thing: tulip
green thing: clover
red thing: strawberry
yellow thing: banana
green thing: grape
For Zsh users, remember arrays start at 1 so this script will work, but instead of indexing with 0-2 in this example, use 1-3.