我正在尝试获取在 for 循环中迭代的数组的索引。我正在做类似的事情
arr=( foo bar baz )
for i in $arr; do
echo "index ${#arr}";
done
但这只给出了数组中元素的数量,而不是当前值在数组中的位置。这个怎么做?
答案1
由于似乎没有人提出明显的答案,我会的。
为什么不直接使用 C 和 Java 等主流语言中使用的数字 for 循环呢?
for ((i = 1; i <= $#arr; i++)); do
echo "Index: $i, value: ${arr[i]}"
done
或者,甚至更短(而且更慢,并且可能会占用大数组的内存):
for i in {1..$#arr}; do
echo "Index: $i, value: ${arr[i]}"
done
答案2
您可以使用数组文字匹配以及返回当前索引的标志来执行此操作:
arr=( foo bar baz )
for i in $arr; do
echo "index ${arr[(ie)$i]}";
done
该i
标志返回索引,并且该e
标志修改i
行为以字面匹配字符串。表达式为: for arr 匹配字符串 $i 按字面意思返回索引。此方法的缺点是,只有当数组的所有元素都是唯一的时,您才可以信任它。否则你需要使用某种计数器。
答案3
从 zsh 5.0.6 开始,您可以通过压缩扩展数组并生成索引:
for k v in "${(@)${=${(eQ):-'$( (( $#ary )) && echo {1..$#ary})'}}:^ary}"; do
[[ -z $k ]] && continue
echo "index: $k - value: $v"
done
我实际上不会使用它(因为担心将来会自我刺伤我),并且对于具有大量元素的数组来说它会很慢。增加计数器会更有效,因为 zsh 中的数组不能稀疏。
答案4
一个“实用”的等效方法(参见注释中的限制),但更简单的方法可以完成 llua 所做的大部分工作,使用粘贴和过程替换:
arr=( foo "bar 't' ttt" baz )
paste <(echo {1..$#arr}"\n") <(echo ${^arr}"\n") | head -n -1 | while read i v; do
echo index $i, val : $v;
done
编辑:这个适用于 zsh 的早期版本并处理空格和引号 (嗯,它不使用 for 但操作说“迭代”而不是“for 循环”
arr=( foo "bar 't' ttt" baz )
paste <(echo {1..$#arr}"\n") <(echo ${^arr}"\n") | head -n -1 | while read i v; do
echo index $i, val : $v;
done