zshで配列インデックスを反復処理する方法は?

Aug 25 2020

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のインデックスを反復処理する適切な方法は何ですか?

回答

6 StéphaneChazelas Aug 24 2020 at 23:50

zsh配列は、他のほとんどのシェルや言語と同様に通常の配列であり、キーが正の整数に制限されているksh / bash連想配列(別名スパース配列)とは異なります。zsh連想配列用の個別の変数タイプがあります(キーは0バイト以上の任意のシーケンスです)。

したがって、通常の配列のインデックスは、常に配列のサイズに対して1の整数です(ksh互換性が有効になっていないと仮定すると、配列のインデックスは1ではなく0から始まります)。

そう:

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のようなシェルでのさまざまなアレイ設計の詳細については、シェルによるアレイサポートのテストを参照してください。

AnaoliyTk Aug 24 2020 at 23:14

この記事で述べたように、Zシェルのユーザーガイド-第5章:置換:

これは、他のパラメーターに対して次のように拡張されます。

% array=(one two three)
% print -l "${array[@]}"
one
two
three

より一般的には、別のフラグを使用したすべての形式の置換(@):

% print -l "${(@)array}"
one
two
three

だから、多分ちょうど2番目の方法を使用してみてください?