Imprima archivos en orden inverso desde una matriz asociativa en bash

Imprima archivos en orden inverso desde una matriz asociativa en bash
for key in ${!current_file[@]} 
    do
      echo $key      
     done

Declaro current_file como a continuación en bash:

declare -A current_file

inserte la clave como archivo y el tamaño como valor en archivo_actual. Salida de las impresiones del bucle for:

file2
file1

Quiero imprimir como:

file1 
file2

¿Cómo puedo imprimir así?

Respuesta1

Para imprimir la lista de claves ordenadas alfabéticamente, y asumiendo GNU sort, podrías hacer:

printf '%s\0' "${!hash[@]}" | sort -z | tr '\0' '\n'

O para iterar sobre la lista ordenada de claves:

while IFS= read -rd '' -u3 key; do
  something with "${hash[$key]}"
done 3< <(printf '%s\0' "${!hash[@]}" | sort -z)

Si puede garantizar que las claves no contendrán caracteres de nueva línea, puede simplificarlo a:

printf '%s\n' "${!hash[@]}" | sort

Con zsh, eso sería:

printf "%s\n" "${(ko@)hash}"

( kpara obtener las claves, opara ordenar esa lista, @entre comillas dobles para conservar la clave vacía, si corresponde (tenga en cuenta que bashactualmente tiene la limitación de que no puede tener un elemento hash con una clave vacía)).

Y para recorrerlos:

for key in "${(ko@)hash}"; do
  something with "$hash[$key]"
done

Tenga en cuenta que, a excepción del último anterior, asumimos que el hash contiene al menos un elemento (ya que printf '%s\0'sin ningún argumento el resultado sería \0como si hubiera un elemento con una clave vacía).

En cualquier caso, escribir ${!current_file[@]}sin comillas tiene muy poco sentido ya que invoca el operador split+glob en esa lista de claves.

Respuesta2

La matriz asociativa bashes como hashes/diccionarios en los lenguajes típicos y, como ellos, está desordenada (en realidad, está ordenada según el valor hash interno). Por lo tanto, no puede esperar que la salida se ordene (generalmente) mientras se itera sobre las claves de la matriz (asociativa).

Debe ordenarlo usted mismo, por ejemplo enviando el STDOUT al STDIN de sort:

for key in ${!current_file[@]}; do
    echo $key      
done | sort 

o algo similar.


Si desea mantener un orden para poder realizar cualquier operación basada en el orden en las claves/valores de la matriz asociativa, puede mantener otra matriz indexada como referencia de inserción. Lo siguiente debería darle una idea 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

información relacionada