Bash 关联数组

作者:Mitch Frazier

bash 的手册页一直存在以下 bug 列表:“它太大了,太慢了”(位于手册页的最底部)。 如果您同意这一点,那么您可能不想阅读 bash 4.0 版本中添加的“新”关联数组。 另一方面,如果您曾经使用过任何现代 Office 套件,并且看到了最糟糕的代码膨胀,并且只是认为 bash 人们有点夸大其词,那么请继续阅读。

bash 中的关联数组没有什么太令人惊讶的,它们正如您可能期望的那样

declare -A aa
aa[hello]=world
aa[ab]=cd

The-A选项声明aa为关联数组。 然后通过将“键”放在方括号内而不是数组索引来进行赋值。 您还可以一次分配多个项目

declare -A aa
aa=([hello]=world [ab]=cd)

检索值也如预期

if [[ ${aa[hello]} == world ]]; then
    echo equal
fi
bb=${aa[hello]}

您还可以使用包含空格或其他“奇怪”字符的键

aa["hello world"]="from bash"

但请注意,当使用括号括起来的列表将多个项目分配给数组时,如果任何键中包含空格,则似乎存在一个 bug。 例如,考虑以下脚本

declare -A b
b=([hello]=world ["a b"]="c d")

for i in 1 2
do
    if [[ ${b["a b"]} == "c d" ]]; then
        echo $i: equals c d
    else
        echo $i: does not equal c d
    fi
    b["a b"]="c d"
done

在顶部,b["a b"]作为一个括号括起来的项列表的一部分被赋值。 在循环内部,if 语句测试该项是否是我们期望的值。 在循环的底部,使用“直接”赋值将相同的值分配给相同的键。 然后循环再次执行一次。 人们会期望 if 测试每次都成功,但事实并非如此

$ bash ba.sh
1: does not equal c d
2: equals c d

如果您将以下内容添加到脚本末尾以打印出所有键,您可以看到问题所在

for k in "${!b[@]}"
do
    echo "$k"
done

你得到的结果是

$ bash ba.sh
1: does not equal c d
2: equals c d
a\ b
a b
hello

您可以在这里看到,第一个赋值,通过列表完成的赋值,错误地将键添加为a\ b而不是简单地作为a b.

在结束之前,我想指出我最近才发现的关于 bash 数组的另一个功能:使用+=运算符扩展它们的能力。 这实际上是让我找到手册页,然后让我发现关联数组功能的原因。 这不是一个新功能,只是对我来说是新的

aa=(hello world)
aa+=(b c d)

+=赋值之后,该数组现在将包含 5 个项目,在+=之后的值已追加到数组的末尾。 这也适用于关联数组。

aa=([hello]=world)
aa+=([b]=c)           # aa now contains 2 items

另请注意,+=运算符也适用于常规变量,并追加到当前值的末尾。

aa="hello"
aa+=" world"          # aa is now "hello world"

有关使用 bash 数组的更多信息,请查看手册页或查看我之前的帖子

Mitch Frazier 是艾默生电气公司的嵌入式系统程序员。 Mitch 自 2000 年代初以来一直是Linux Journal的贡献者和朋友。

加载 Disqus 评论