Wie iteriere ich über Array-Indizes in zsh?
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
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
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?