Bash tableau associatif tri par valeur

j'obtiens le résultat suivant:

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999

Qui est le résultat du script suivant:

for k in "${!authors[@]}"
do
    echo $k ' - ' ${authors["$k"]}
done   

Tout ce que je veux est d'obtenir à la sortie comme ceci:

Pushkin - 100500 
Dostoyevsky - 9999
Gogol - 23

ce qui signifie que les clés dans le tableau associatif doivent être triées par valeur. Est-il une méthode simple pour le faire?

18
demandé sur Charles Duffy 2011-11-21 22:59:15

3 réponses

Vous pouvez facilement trier votre sortie, dans l'ordre numérique décroissant de la 3ème champ:

for k in "${!authors[@]}"
do
    echo $k ' - ' ${authors["$k"]}
done |
sort -rn -k3

voir sort (1) pour plus d'informations sur le sort la commande. Cela permet juste de trier les lignes de sortie; Je ne sais pas comment trier un tableau directement dans bash.

Je ne vois pas non plus comment ce qui précède peut vous donner des noms ("Pushkin" et al.) comme la matrice de touches. Dans bash, les clés de tableau sont toujours des entiers.

18
répondu Andrew Schulman 2011-11-21 19:27:14

Vous pouvez aussi trier les index et utiliser la liste des index triés pour faire une boucle à travers le tableau:

authors_indexes=( ${!authors[@]} )
IFS=$'\n' authors_sorted=( $(echo -e "${authors_indexes[@]/%/\n}" | sed -r -e 's/^ *//' -e '/^$/d' | sort) )

for k in "${authors_sorted[@]}"; do
  echo $k ' - ' ${authors["$k"]}
done 
7
répondu Werner Lehmann 2012-10-01 21:47:08

étendre la réponse de @AndrewSchulman, en utilisant -rn comme option de tri global inverse toutes les colonnes. Dans cet exemple, les auteurs avec la même valeur de tableau associatif seront produits par ordre inverse de nom.

Par exemple

declare -A authors
authors=( [Pushkin]=10050 [Gogol]=23 [Dostoyevsky]=9999 [Tolstoy]=23 )

for k in "${!authors[@]}"
do
  echo $k ' - ' ${authors["$k"]}
done | sort -rn -k3

sortie

Pushkin  -  10050
Dostoyevsky  -  9999
Tolstoy  -  23
Gogol  -  23
Options pour le tri des colonnes spécifiques peuvent être fournies après le spécificateur de colonne. i.e. sort -k3rn

notez que les clés peuvent être spécifiées comme des portées. Ici -k3 arrive à être bien parce que c'est la portée finale, mais pour utiliser seulement la colonne 3 explicitement (dans le cas où d'autres colonnes ont été ajoutées), il doit être spécifié comme -k3,3, De même pour trier par colonne trois dans l'ordre décroissant, puis une colonne dans l'ordre croissant (ce qui est probablement ce qui est souhaité dans cet exemple):

declare -A authors
authors=( [Pushkin]=10050 [Gogol]=23 [Dostoyevsky]=9999 [Tolstoy]=23 )
for k in "${!authors[@]}"
do
  echo $k ' - ' ${authors["$k"]}
done | sort -k3,3rn -k1,1

sortie

Pushkin  -  10050
Dostoyevsky  -  9999
Gogol  -  23
Tolstoy  -  23
3
répondu WaffleSouffle 2018-02-02 15:19:53