Come eseguire l'iterazione sugli indici dell'array in zsh?

Aug 25 2020

In bash possiamo iterare sull'indice di un array come questo

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

dove test è un array, diciamo,

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

in modo che l'output assomigli

0
1
2
3

Tuttavia, quando faccio lo stesso in zsh ottengo un errore:

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

Cosa sta succedendo?

Qual è il modo corretto di iterare sugli indici in zsh?

Risposte

6 StéphaneChazelas Aug 24 2020 at 23:50

zshgli array sono array normali come nella maggior parte delle altre shell e linguaggi, non sono come negli array associativi ksh/bash con chiavi limitate a numeri interi positivi (ovvero array sparsi). zshha un tipo di variabile separato per gli array associativi (con le chiavi che sono sequenze arbitrarie di 0 o più byte).

Quindi gli indici per gli array normali sono sempre numeri interi da 1 alla dimensione dell'array (supponendo che la compatibilità ksh non sia abilitata, nel qual caso gli indici dell'array iniziano da 0 invece che da 1).

Così:

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

Sebbene in genere, eseguirai il ciclo sui membri dell'array, non sul loro indice:

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

(la "$array[@]"sintassi, al contrario di $array, conserva gli elementi vuoti).

O:

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

per passare tutti gli elementi a un comando.

Ora, per scorrere le chiavi di un array associativo , la sintassi è:

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

(con di nuovo @dentro le virgolette utilizzate per preservare gli elementi vuoti).

Sebbene tu possa anche passare chiavi e valori ai comandi con:

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

Per ulteriori informazioni sulle varie progettazioni di array nelle shell simili a Bourne, vedere Test per il supporto di array tramite shell

AnaoliyTk Aug 24 2020 at 23:14

Come detto in questo articolo Guida per l'utente alla Z-Shell - Capitolo 5: Sostituzioni :

Questo viene esteso per altri parametri nel modo seguente:

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

e più in generale per tutte le forme di sostituzione utilizzando un altro flag, (@):

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

Quindi, forse prova solo a usare il secondo modo?