如何在 zsh 中迭代数组索引?

如何在 zsh 中迭代数组索引?

在 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
%

相关内容