Bash associative array sorting by value
The best way to sort a bash associative array by VALUE is to NOT sort it.
Instead, get the list of VALUE:::KEYS, sort that list into a new KEY LIST, and iterate through the 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]
Alternatively you can sort the indexes and use the sorted list of indexes to loop through the array:
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
Extending the answer from @AndrewSchulman, using -rn as a global sort option reverses all columns. In this example, authors with the same associative array value will be output by reverse order of name.
For example
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
will output
Pushkin - 10050 Dostoyevsky - 9999 Tolstoy - 23 Gogol - 23Options for sorting specific columns can be provided after the column specifier. i.e.
sort -k3rn
Note that keys can be specified as spans. Here -k3
happens to be fine because it is the final span, but to use only column 3 explicitly (in case further columns were added), it should be specified as -k3,3
,
Similarly to sort by column three in descending order, and then column one in ascending order (which is probably what is desired in this example):
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
will output
Pushkin - 10050 Dostoyevsky - 9999 Gogol - 23 Tolstoy - 23
You can easily sort your output, in descending numerical order of the 3rd field:
for k in "${!authors[@]}"
do
echo $k ' - ' ${authors["$k"]}
done |
sort -rn -k3
See sort(1) for more about the sort
command. This just sorts output lines; I don't know of any way to sort an array directly in bash.
I also can't see how the above can give you names ("Pushkin" et al.) as array keys. In bash, array keys are always integers.