Bash 关联数组按值排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8217049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:13:33  来源:igfitidea点击:

Bash associative array sorting by value

bashassociative-arraysorting

提问by Graf

I get the following output:

我得到以下输出:

Pushkin - 100500 
Gogol - 23 
Dostoyevsky - 9999

Which is the result of the following script:

这是以下脚本的结果:

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

All I want is to get the output like this:

我想要的只是得到这样的输出:

Pushkin - 100500 
Dostoyevsky - 9999
Gogol - 23

which means that the keys in associative array should be sorted by value. Is there an easy method to do so?

这意味着关联数组中的键应该按值排序。有没有一种简单的方法可以做到这一点?

回答by Andrew Schulman

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 sortcommand. This just sorts output lines; I don't know of any way to sort an array directly in bash.

有关该sort命令的更多信息,请参阅 sort(1) 。这只是对输出行进行排序;我不知道有什么方法可以直接在 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.

我也看不到上面的内容如何为您提供名称(“Pushkin”等)作为数组键。在 bash 中,数组键总是整数。

回答by Werner Lehmann

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 

回答by WaffleSouffle

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.

扩展@AndrewSchulman 的答案,使用 -rn 作为全局排序选项会反转所有列。在这个例子中,具有相同关联数组值的作者将按姓名的相反顺序输出。

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  -  23
可以在列说明符之后提供用于对特定列进行排序的选项。IEsort -k3rnsort -k3rn

Note that keys can be specified as spans. Here -k3happens 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):

请注意,键可以指定为跨度。这里-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

will output

会输出

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

回答by mz4wheeler

The best way to sort a bash associative array by VALUE is to NOT sort it.

按 VALUE 对 bash 关联数组进行排序的最佳方法是不对它进行排序。

Instead, get the list of VALUE:::KEYS, sort that list into a new KEY LIST, and iterate through the list.

相反,获取 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 }'
)

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]