
for key in ${!current_file[@]}
do
echo $key
done
Declaro current_file como abaixo no bash:
declare -A current_file
insira a chave como um arquivo e o tamanho como valor em arquivo_atual. Saída das impressões do loop for:
file2
file1
Quero imprimir como:
file1
file2
Como posso imprimir assim?
Responder1
Para imprimir a lista de chaves ordenadas em ordem alfabética, e assumindo GNU sort
, você poderia fazer:
printf '%s\0' "${!hash[@]}" | sort -z | tr '\0' '\n'
Ou para iterar na lista classificada de chaves:
while IFS= read -rd '' -u3 key; do
something with "${hash[$key]}"
done 3< <(printf '%s\0' "${!hash[@]}" | sort -z)
Se você puder garantir que as chaves não conterão caracteres de nova linha, poderá simplificá-las para:
printf '%s\n' "${!hash[@]}" | sort
Com zsh
, isso seria:
printf "%s\n" "${(ko@)hash}"
( k
para obter as chaves, o
para ordenar essa lista, @
entre aspas duplas para preservar a chave vazia, se houver (observe que bash
atualmente tem uma limitação: não pode ter um elemento hash com uma chave vazia)).
E para fazer um loop sobre eles:
for key in "${(ko@)hash}"; do
something with "$hash[$key]"
done
Observe que, exceto pelo último acima, estamos assumindo que o hash contém pelo menos um elemento (já que printf '%s\0'
sem nenhum argumento ainda seria gerado \0
como se houvesse um elemento com uma chave vazia).
Em qualquer caso, escrever ${!current_file[@]}
sem aspas faz muito pouco sentido, pois invoca o operador split+glob nessa lista de chaves.
Responder2
A matriz associativa bash
é como hashes/dicionários em linguagens típicas e, como eles, não é ordenada (na verdade, ordenada de acordo com o valor do hash interno). Portanto, você não pode esperar que a saída seja (geralmente) classificada durante a iteração nas chaves da matriz (associativas).
Você precisa classificar você mesmo, por exemplo, enviando o STDOUT para o STDIN de sort
:
for key in ${!current_file[@]}; do
echo $key
done | sort
ou algo semelhante.
Se você deseja manter um pedido para poder realizar qualquer operação baseada em pedido nas chaves/valores do array associativo, você pode manter outro array indexado como referência de inserção. O seguinte deve lhe dar uma ideia básica:
## Associative array `foo`
$ declare -A foo=([spam]=egg [baz]=cool)
## Reference indexed array `bar` containing the keys of `foo` sequentially indexed
$ bar=(spam baz)
## Retrieving in forward order
$ for i in "${bar[@]}"; do echo "$i :: ${foo[$i]}"; done
spam :: egg
baz :: cool
## Retrieving in reverse order
$ for ((i=${#bar[@]}-1; i>=0; i--)); do idx="${bar[$i]}"; echo "$idx :: ${foo[$idx]}"; done
baz :: cool
spam :: egg