It:
key="index"; arr[$key]="val" echo ${arr[${key}]}
only works. Since arr is a regular array, not an associative array, it can only be indexed with non-negative integer values.
Consider this valid code:
index=42 key="index" arr[$key]="val" echo ${arr[42]} echo ${arr[index]} echo ${arr[$index]} echo ${arr['index']} echo ${arr["index"]} echo ${arr[\index]}
All echo statements print val . Since an index is considered an arithmetic expression, it can refer to a variable (in this case, $index ) either with the $ prefix or without it, even if it is a quoted string.
In your code, where you never assigned a value to $index , ${arr[${key}]} expands to ${arr[index]} , which is equivalent to the ${arr[$index]} that is being processed (by default) as equivalent to ${arr[0]} .
(If you have set -o nounset , then references to undefined variables are treated as errors, and your code will generate an error message.)
Second code snippet:
key="index.index"; arr[$key]="val" echo ${arr[${key}]}
incorrect since index.index not a valid variable name, although you probably meant that it was just a string used as the index of an array.
If you want arr to allow arbitrary strings as indices, it must be an associative array. You can create a non-associative array by simply assigning it (or using declare -a ), but an associative array can only be created using declare -a .
Associative arrays were added to bash in version 4. If you are using an earlier version of bash, declare -a not supported. You will need to upgrade to a new bash, copy some awkward alternative, or use a language that supports associative arrays like Awk, Python or Perl.
Adding declare -A arr (as user000001 the answer suggests) should solve the problem (if you have bash 4), but it is instructive to understand what your source code is (or rather does not).
(By the way, thanks for that, I learned a lot when I wrote this answer.)