2

I've been going through the "Bash Pocket Reference" book and I got to the section about associative arrays. Now, trying the example code in the book gives me unexpected answers:

istanev@inspiron5559:~$ data=([joe]=30 [mary]=25)
istanev@inspiron5559:~$ echo ${data[joe]}
25
istanev@inspiron5559:~$ echo ${data[mary]}
25

Isn't data[joe] supposed to return 30? Why is it returning 25 instead? My bash version is 4.3.46(1)-release.

  • Hmm, but I get bash: declare: data: cannot convert indexed to associative array. EDIT: Never mind, got it to work :) So I have to declare it before assigning it – Ivan Stanev Dec 3 '16 at 17:02
  • 2
    unset data; declare -A data=([joe]=30 [mary]=25) – Cyrus Dec 3 '16 at 17:07
1

By default bash process arrays as indexed arrays.
In such case indexes are evaluated as an Arithmetic Expression.

$ joe=3    mary=6
$ unset data
$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -a data=([3]="111" [6]="bbb")

The output reveals several things:

  • The array is indexed: the -a in the output.
  • The array does contain two values.
  • The indexes of the values match the numeric values of variables joe and mary.
  • The values contained in the array may be strings.

That is so even if the indexes are quoted (even single quotes):

$ joe=3    mary=6
$ unset data
$ data=(["joe"]=111 ["mary"]=bbb)
$ declare -p data
declare -a data=([3]="111" [6]="bbb") 

If the strings used as indexes have not been defined to contain a number, are anyway evaluated as an Arithmetic Expression that has zero value.

$ unset joe    ;    unset mary    ;    unset data
$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -a data=([0]="bbb")

What happened is that [joe]=111 evaluated to [0]=111, setting the array at index 0 to 111. But then, [mary]=bbb evaluated to [0]=bbb, thus replacing the array value at index 0 to bbb.

To actually have an Associative array it has to be defined as so before its use.
It can not be changed while it contains data. With the array set as above:

$ declare -A data
bash: declare: data: cannot convert indexed to associative array

But clearing it, we can:

$ joe=3  ;  mary=6  ; unset data

$ declare -A data

$ data=([joe]=111 [mary]=bbb)
$ declare -p data
declare -A data=([joe]="111" [mary]="bbb" )

As you can see, it doesn't matter that the strings used as indexes are also valid variable names and that they contain a value. They are used as string indexes for the Associative array.

| improve this answer | |
1

Associative arrays need to be declared explicitly, with typeset -A or something equivalent (declare -A or readonly -A in bash). By default, an array is a “plain” array, with integer indices. Non-numeric indexes on integer-indexed arrays are interpreted as arithmetic expressions, and unset variable names in arithmetic expressions are silently interpreted as 0, so data=([joe]=30 [mary]=25) sets data[0]=30, then data[0]=25, and ${data[whatever]} is element 0 which is 25.

bash-4.3$ indexed=([a]=aye [b]=bee [x+1]=cee)
bash-4.3$ echo length=${#indexed[@]} a=${indexed[a]} b=${indexed[b]} x+1=${indexed[x+1]} 1=${indexed[1]}
length=2 a=bee b=bee x+1=cee 1=cee
bash-4.3$ typeset -A associative=([a]=aye [b]=bee [x+1]=cee)
bash-4.3$ echo length=${#associative[@]} a=${associative[a]} b=${associative[b]} x+1=${associative[x+1]} 1=${associative[1]}
length=3 a=aye b=bee x+1=cee 1=

Since indexed is an array with numeric indices, indexed[a] and indexed[b] are both indexed[0], and indexed[x+1] is indexed[1]. With an associative array, what is inside the bracket parsed as a string (with the usual expansions as in double quotes, so you can write ${associative[$key]}).

| improve this answer | |
  • Sorry @Gilles, but "Non-numeric indexes on integer-indexed arrays are silently interpreted as 0" is not the whole truth. Whatever is inside the […] is evaluated as an Arithmetic Expression. Yes, it may evaluate to 0, but …, may as well, not. Read my answer. – Isaac Dec 4 '16 at 2:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.