从关联数组中检索的值错误?

从关联数组中检索的值错误?

我一直在阅读“Bash Pocket Reference”一书,并阅读了有关关联数组的部分。现在,尝试书中的示例代码给了我意想不到的答案:

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

data[joe] 不是应该返回 30 吗?为什么它返回 25?我的 bash 版本是 4.3.46(1)-release。

答案1

默认情况下,bash 将数组处理为索引数组。
在这种情况下,索引被评估为算术表达式。

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

输出揭示了几件事:

  • 该数组被索引:-a在输出中。
  • 该数组确实包含两个值。
  • joe值的索引与变量和的数值相匹配mary
  • 数组中包含的值可以是字符串。

即使索引被引用(甚至单引号)也是如此:

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

如果用作索引的字符串尚未定义为包含数字,则无论如何都会将其计算为具有零值的算术表达式。

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

发生的情况是,[joe]=111计算结果为[0]=111,将索引处的数组设置0111。但随后,[mary]=bbb计算结果为[0]=bbb,从而将索引处的数组值替换0bbb

要真正拥有关联数组,必须在使用之前对其进行定义。
当它包含数据时不能更改。数组设置如上:

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

但是清除它,我们可以:

$ joe=3  ;  mary=6  ; unset data

$ declare -A data

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

正如您所看到的,用作索引的字符串也是有效的变量名称并且它们包含值并不重要。它们用作关联数组的字符串索引。

答案2

关联数组需要使用typeset -A或等效的东西(declare -Areadonly -A在 bash 中)显式声明。默认情况下,数组是一个“普通”数组,具有整数索引。整数索引数组上的非数字索引被解释为算术表达式,而算术表达式中未设置的变量名会默认解释为 0,因此data=([joe]=30 [mary]=25)设置data[0]=30、thendata[0]=25${data[whatever]}is 元素 0,即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=

因为indexed是一个具有数字索引的数组,indexed[a]并且indexed[b]都是indexed[0],并且indexed[x+1]indexed[1]。对于关联数组,括号内的内容被解析为字符串(使用双引号中的通常扩展,因此您可以编写${associative[$key]})。

相关内容