web-dev-qa-db-ja.com

値によるBash連想配列の並べ替え

次の出力が得られます。

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999

これは、次のスクリプトの結果です。

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

私が欲しいのは、次のような出力を取得することです。

Pushkin - 100500 
Dostoyevsky - 9999
Gogol - 23

これは、連想配列のキーを値でソートする必要があることを意味します。そうする簡単な方法はありますか?

21
Graf

3番目のフィールドの番号の降順で、出力を簡単に並べ替えることができます。

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

sortコマンドの詳細については、sort(1)を参照してください。これは出力行をソートするだけです。配列をbashで直接ソートする方法がわかりません。

また、上記で配列キーとして名前( "Pushkin" et al。)を指定する方法もわかりません。 bashでは、配列キーは常に整数です。

25
Andrew Schulman

または、インデックスを並べ替え、並べ替えられたインデックスのリストを使用して、配列をループすることもできます。

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
Werner Lehmann

Bash連想配列をVALUEで並べ替える最良の方法は、並べ替えないことです。

代わりに、VALUE ::: KEYSのリストを取得し、そのリストを新しいKEY LISTに並べ替えて、リストを繰り返し処理します。

declare -A ADDR
ADDR[192.168.1.3]="Host3"
ADDR[192.168.1.1]="Host1"
ADDR[192.168.1.2]="Host2"

KEYS=$(
for KEY in ${!ADDR[@]}; do
  echo "${ADDR[$KEY]}:::$KEY"
done | sort | awk -F::: '{print $2}'
)

for KEY in $KEYS; do
  VAL=${ADDR[$KEY]}
  echo "KEY=[$KEY] VAL=[$VAL]"
done

output:
KEY=[192.168.1.1] VAL=[Host1]
KEY=[192.168.1.2] VAL=[Host2]
KEY=[192.168.1.3] VAL=[Host3]
2
mz4wheeler