循环遍历关联数组不符合预期

Looping through associative array not as expected

根据 Associative arrays in zsh 中描述的方法,我尝试了以下脚本来测试 Zsh 5.5.1 中关联数组的循环:

typeset -A emap
emap=( X y U v )
for key val in ${(kv)emap}
do
  echo key=$key val=$val
done

我得到了预期的输出

key=U val=v
key=X val=y

但是当我这样写例子的时候:

env_code ()
{
  typeset -A emap
  emap=( MX1 Mme VOX Vbo MS1 Msc JRUBY_VERSION '()' FOO '')
  local ename
  local abbr
  for ename abbr in ${(kv)emap}
  do
    echo ename=$ename abbr=$abbr
  done
}
env_code # Invoking the function

我得到输出

ename=FOO abbr=JRUBY_VERSION
ename=() abbr=MX1
ename=Mme abbr=MS1
ename=Msc abbr=VOX
ename=Vbo abbr=

我们看到键和值已交换。我会期待输出

ename=MX1 abbr=Mme
ename=VOX abbr=Vbo

数组本身完好无损:

% typeset -A emap
% emap=( MX1 Mme VOX Vbo MS1 Msc JRUBY_VERSION '()' FOO '')
% declare -p emap
typeset -A emap=( [FOO]='' [JRUBY_VERSION]='()' [MS1]=Msc [MX1]=Mme [VOX]=Vbo)

请特别注意键值对的顺序

但是,当您不带引号展开 ${(kv)emap} 时,键 FOO 的空字符串值将丢失。

% print -l ${(kv)emap}
FOO
JRUBY_VERSION
()
MX1
Mme
MS1
Msc
VOX
Vbo

因此,FOO 是 "mapped" 到值 JRUBY_VERSION,而不是 ''

引用扩展可以恢复预期的行为。使用引号,您需要显式索引操作来生成 print.

的各个参数
% print -l "${(kv)emap[@]}"
FOO

JRUBY_VERSION
()
MX1
Mme
MS1
Msc
VOX
Vbo

没有[@],空字符串仍然保留,只是更难注意到。

% print -l "${(kv)emap}"
FOO  JRUBY_VERSION () MX1 Mme MS1 Msc VOX Vbo

# Note the two spaces between FOO and JRUBY_VERSION.

未加引号的参数扩展不受单词拆分的影响,但它们 受引号删除的影响,并且没有 个字符留在引号从空字符串中删除,展开后没有参数。