在 bash 中我们可以像这样迭代数组的索引
~$ for i in "${!test[@]}"; do echo $i; done
其中 test 是一个数组,例如
~$ test=(a "b c d" e f)
这样输出看起来像
0
1
2
3
但是,当我在 zsh 中执行相同操作时,出现错误:
➜ ~ for i in "${!test[@]}"; do echo $i; done
zsh: event not found: test[@]
到底是怎么回事?
在 zsh 中迭代索引的正确方法是什么?
答案1
zsh
数组是普通数组,就像大多数其他 shell 和语言的数组一样,它们与 ksh/bash 中的关联数组不同,键仅限于正整数(也称为稀疏数组)。zsh
对于关联数组有一个单独的变量类型(键是 0 或更多字节的任意序列)。
因此,普通数组的索引始终是从 1 到数组大小的整数(假设未启用 ksh 兼容性,在这种情况下数组索引从 0 而不是 1 开始)。
所以:
typeset -a array
array=(a 'b c' '')
for ((i = 1; i <= $#array; i++)) print -r -- $array[i]
不过通常情况下,您会遍历数组成员,而不是遍历它们的索引:
for i ("$array[@]") print -r -- $i
(该"$array[@]"
语法与 相反$array
,保留空元素)。
或者:
print -rC1 -- "$array[@]"
将所有元素传递给命令。
现在,循环一个关联数组,语法为:
typeset -A hash
hash=(
key1 value1
key2 value2
'' empty
empty ''
)
for key ("${(@k)hash}") printf 'key=%s value=%s\n' "$key" "$hash[$key]"
(再次@
使用内部引号来保留空元素)。
尽管您也可以使用以下命令将键和值传递给命令:
printf 'key=%s value=%s\n' "${(@kv)hash}"
有关 Bourne 类 shell 中各种数组设计的更多信息,请参阅测试 shell 对数组的支持
答案2
正如这篇文章所说Z-Shell 用户指南 - 第 5 章:替换:
这可以通过以下方式扩展到其他参数:
% array=(one two three)
% print -l "${array[@]}"
one
two
three
更一般地,对于使用另一个标志 (@) 的所有形式的替换:
% print -l "${(@)array}"
one
two
three
那么,也许尝试使用第二种方法?
答案3
并带有大括号{ }
:
% test=(a "b c d" e f)
% for i in {1..$#test}; do echo $i; done
1
2
3
4
%