Wie iteriere ich über Array-Indizes in zsh?

Aug 25 2020

In Bash können wir über den Index eines Arrays wie dieses iterieren

~$ for i in "${!test[@]}"; do echo $i; done

wo test ein Array ist, sagen wir,

~$ test=(a "b c d" e f)

so dass die Ausgabe aussieht wie

0
1
2
3

Wenn ich jedoch dasselbe in zsh mache, erhalte ich eine Fehlermeldung:

➜ ~ for i in "${!test[@]}"; do echo $i; done
zsh: event not found: test[@]

Was ist los?

Was ist der richtige Weg, um Indizes in zsh zu durchlaufen?

Antworten

6 StéphaneChazelas Aug 24 2020 at 23:50

zshArrays sind normale Arrays wie in den meisten anderen Shells und Sprachen. Sie sind nicht wie in assoziativen ksh / bash-Arrays mit Schlüsseln, die auf positive ganze Zahlen (auch als spärliche Arrays bezeichnet) beschränkt sind. zshhat einen separaten Variablentyp für assoziative Arrays (wobei Schlüssel beliebige Sequenzen von 0 oder mehr Bytes sind).

Daher sind die Indizes für normale Arrays immer ganze Zahlen 1 zur Größe des Arrays (vorausgesetzt, die ksh-Kompatibilität ist nicht aktiviert. In diesem Fall beginnen die Array-Indizes bei 0 anstelle von 1).

So:

typeset -a array
array=(a 'b c' '')
for ((i = 1; i < $#array; i++)) print -r -- $array[i]

Im Allgemeinen würden Sie jedoch die Array-Mitglieder und nicht deren Index durchlaufen:

for i ("$array[@]") print -r -- $i

(Die "$array[@]"Syntax behält im Gegensatz zu $arraydie leeren Elemente bei).

Oder:

print -rC1 -- "$array[@]"

um alle Elemente an einen Befehl zu übergeben.

Um nun die Schlüssel eines assoziativen Arrays zu durchlaufen, lautet die Syntax:

typeset -A hash
hash=(
  key1 value1
  key2 value2
  '' empty
  empty ''
)
for key ("${(@k)hash}") printf 'key=%s value=%s\n' "$key" "$hash[$key]"

(mit wieder @inneren Anführungszeichen, um leere Elemente zu erhalten).

Sie können jedoch auch Schlüssel und Werte an Befehle übergeben mit:

printf 'key=%s value=%s\n' "${(@kv)hash}"

Weitere Informationen zu den verschiedenen Array-Designs in Bourne-ähnlichen Shells finden Sie unter Testen der Array-Unterstützung nach Shell

AnaoliyTk Aug 24 2020 at 23:14

Wie in diesem Artikel erwähnt Ein Benutzerhandbuch für die Z-Shell - Kapitel 5: Substitutionen :

Dies wird für andere Parameter folgendermaßen erweitert:

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

und allgemeiner für alle Formen der Substitution unter Verwendung eines anderen Flags (@):

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

Also, vielleicht versuchen Sie es einfach mit dem zweiten Weg?