Сортировка ассоциативных массивов Bash по значению
Я получаю следующий вывод:
Pushkin - 100500
Gogol - 23
Dostoyevsky - 9999
Это результат следующего script:
for k in "${!authors[@]}"
do
echo $k ' - ' ${authors["$k"]}
done
Все, что я хочу, это получить такой вывод:
Pushkin - 100500
Dostoyevsky - 9999
Gogol - 23
что означает, что ключи в ассоциативном массиве должны сортироваться по значению. Есть ли простой способ сделать это?
Ответы
Ответ 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]