关联数组的键 ${!a[@]} 和值 ${a[@]} 是否以相同的顺序展开?

Soc*_*owi 5 bash associative-array

在 bash 中,关联数组(也称为字典或哈希映射)是无序的。对于关联数组,a我们可以列出带有 的所有键(也称为索引)和带有 的${!a[@]}所有值${a[@]}。我知道这些结构不会以固定的顺序展开。我想知道是否至少有一些保证。我找不到任何。然而,[ "${a[*]}" = ${a[*]} ]在任何实施中都会失败似乎是不现实的。同样,它似乎${!a[@]}以与${a[@]}. 如果我们x在位置n in找到键,${!a[@]}那么我们也会${a[x]}在位置n in找到值${a[@]}。当然,我们假设和a的扩展之间没有修改。${!a[@]}${a[@]}

例子:

declare -A a=([x]=1 [y]=2 [z]=3)
printf %s\\n "${!a[*]}" "${a[*]}"

# As output I would expect one of the following blocks ...
# (corresponding keys and values are in the same column)
x y z    x z y    y x z    y z x    z x y    z y x
1 2 3    1 3 2    2 1 3    2 3 1    3 1 2    3 2 1

# ... but never something like ...
# (at least one key doesn't share a column with its value)
x y z    x y z    y x z
1 3 2    2 3 1    2 3 1    ...
Run Code Online (Sandbox Code Playgroud)

  • 对于任何现有的bash版本和关联数组a,可以${!a[@]}${a[@]}以这样的方式展开键和及其对应的值有不同的顺序?换句话说:

# Are there values for a and i
# such that this script could print "different order"
declare -A a=(...)
declare -i i=...
keys=("${!a[@]}")
values=("${a[@]}")
[ "${a[keys[i]]}" != "${values[i]}" ] && echo "different order"
Run Code Online (Sandbox Code Playgroud)

奖金问题

  • bash的手册或其他一些官方文档中的和扩展顺序是否有任何保证${!a[*]}${a[@]}
  • 我们可以从实现本身中承担进一步/其他保证吗?这些保证中的一些是否随着 bash 的不同版本而改变?在即将发布的 bash 版本中,这些保证中的一些可能会改变吗?

Per*_*car 2

我在 bash 手册页中没有看到任何提及关联数组的键排序(我使用的是 4.3.48)。查看 bash 5.0 ( ) 的源代码hashlib.c还表明,bash 使用最简单的基于散列 XOR 的算法,没有任何随机化,因此顺序不应在进程或机器之间随机化,这与您在其中找到的其他一些更复杂的算法不同,珀尔。

话虽如此,正如 Perl-land 的经验告诉我们的那样,依赖特定的键顺序或顺序保持不变仍然是不明智的。此外,由于 bash 手册页没有说明排序,因此无法保证。哈希实现可以随时替换或重写。