循环遍历关联数组不符合预期
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.
未加引号的参数扩展不受单词拆分的影响,但它们 受引号删除的影响,并且没有 个字符留在引号从空字符串中删除,展开后没有参数。
根据 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.
未加引号的参数扩展不受单词拆分的影响,但它们 受引号删除的影响,并且没有 个字符留在引号从空字符串中删除,展开后没有参数。