0

I have the following simple code in bash:

declare -A numbers

one_to_two=("one" "two")
three_to_four=("three" "four")


numbers["first"]="${one_to_two[@]}"
numbers["second"]="${three_to_four[@]}"

for var in "${!numbers[@]}"; do
  values=("${numbers[$var]}")
  for value in "${values[@]}"; do
    echo -e "value: $value\n"
  done
done

I was expecting to get something such as:

value: one

value: two

value: three

value: four

but instead I've got:

value: three four

value: one two

What am I missing? I have not much experience in bash

jei L
  • 33
  • 6
  • `bash` does not support multi-dimensional arrays (aka arrays of arrays); to emulate multi-dimensional arrays you need to get 'creative'; one approach is namerefs - same thing Charles Duffy has referred to as namevars; another approach would be a concatenated key for an associative array (eg, `numbers[first:one]`) though this can get messy due to haveing to 'break apart' the index when trying to loop through the array – markp-fuso Aug 12 '23 at 17:42
  • See [How to declare 2D array in bash](https://stackoverflow.com/q/16487258/4154375) and [Multi-dimensional arrays in Bash](https://stackoverflow.com/q/11233825/4154375). – pjh Aug 13 '23 at 09:49

1 Answers1

2

When you run numbers["first"]=${one_to_two[@]}, the ${array[@]} instead acts like ${array[*]}, flattening the array to a string, because only a string is valid on the right-hand side of that assignment: Associative arrays can only store strings as values.

What you can do instead is use namevars to refer back to the original array variables.

declare -A numbers

one_to_two=("one" "two")
three_to_four=("three" "four")

numbers["first"]=one_to_two
numbers["second"]=three_to_four

for var in "${!numbers[@]}"; do
  declare -n values=${numbers[$var]}
  for value in "${values[@]}"; do
    echo "value from $var: $value"
  done
  unset -n values
done

properly emits:

value from first: one
value from first: two
value from second: three
value from second: four
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Ohhh Interesting, thank you a lot! didn't know this behaviour in Bash! :) – jei L Aug 12 '23 at 13:32
  • @jeiL Bash is *extremely* limited in the data structures it can use. For most purposes, it only has one: the string. Arrays aren't really a data type in bash, just a sort of super-variable that can store more than one item... but the only type of item it can store is a string. – Gordon Davisson Aug 13 '23 at 07:39