Подтвердить что ты не робот

Сортировка ассоциативных массивов Bash по значению

Я получаю следующий вывод:

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999

Это результат следующего script:

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

Все, что я хочу, это получить такой вывод:

Pushkin - 100500 
Dostoyevsky - 9999
Gogol - 23

что означает, что ключи в ассоциативном массиве должны сортироваться по значению. Есть ли простой способ сделать это?

4b9b3361

Ответ 1

Вы можете легко отсортировать свой результат в нисходящем числовом порядке третьего поля:

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

Подробнее о команде sort см. в разделе (1). Это просто сортирует выходные строки; Я не знаю, как отсортировать массив непосредственно в bash.

Я также не вижу, как это может дать вам имена ( "Пушкин" и др.) в виде ключей массива. В bash ключи массива всегда целые числа.

Ответ 2

В качестве альтернативы вы можете сортировать индексы и использовать отсортированный список индексов для цикла через массив:

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 

Ответ 3

Расширение ответа от @AndrewSchulman с использованием -rn в качестве глобального параметра сортировки приводит к инверсии всех столбцов. В этом примере авторы с одинаковым значением ассоциативного массива будут выводиться в обратном порядке имен.

Например

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

выдаст

Pushkin  -  10050
Dostoyevsky  -  9999
Tolstoy  -  23
Gogol  -  23
Опции для сортировки определенных столбцов могут быть предоставлены после спецификатора столбца. т.е. sort -k3rn

Обратите внимание, что ключи могут быть указаны как промежутки. Здесь -k3 бывает хорошо, потому что это последний диапазон, но чтобы явно использовать только столбец 3 (в случае добавления дополнительных столбцов), он должен быть указан как -k3,3, аналогично сортировке по столбцу три в порядке убывания порядок, а затем столбец один в порядке возрастания (что, вероятно, является желательным в этом примере):

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

выведет

Pushkin  -  10050
Dostoyevsky  -  9999
Gogol  -  23
Tolstoy  -  23

Ответ 4

Лучший способ сортировки ассоциативного массива 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]