在awk中对关联数组进行排序

29

我在 awk 中有一个关联数组,它是这样填充的:

chr_count[$3]++

当我尝试打印我的chr_counts时,我使用以下代码:

for (i in chr_count) {
    print i,":",chr_count[i];
}

但是毫不奇怪,i的顺序并没有以任何方式排序。 有没有一种简单的方法来迭代chr_count的排序键?


2
如果您有gawk 4,使用PROCINFO["sorted_in"] = "@val_num_asc"等非常简单。手册展示了许多不同的选项,如果您想要按值/键、数字/字符串、自定义函数等进行降序/升序排序:https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning - unhammer
5个回答

38

不要使用asort,而是使用asorti(source, destination),它将对索引排序并生成一个新数组,你不需要复制原始数组。

然后你可以使用目标数组作为源数组的指针。

对于你的示例,你可以像这样使用它:

n=asorti(chr_count, sorted)
for (i=1; i<=n; i++) {
        print sorted[i] " : " chr_count[sorted[i]]
}

1
哇,完全忘记了尽管在文档中已经读过它。这绝对是更好的答案。 - Cascabel
2
asorti在nawk-20121220-2.fc20.x86_64上无法工作。 - Cristian Ciupitu
1
@CristianCiupitu:抱歉,asorti是GAWK特有的。实际上,我认为nawk没有任何内置的排序函数。 - Dennis Williamson
2
GNU Awk的文档提到:“asort()和asorti()是gawk扩展;它们在兼容模式下不可用(请参见选项)”。 - Cristian Ciupitu

16

您可以使用sort命令。例如:

for ( i in data )
 print i ":", data[i]  | "sort"

14

我最近遇到了这个问题,发现使用gawk可以通过设置PROCINFO["sorted_in"]的值来控制迭代顺序。我在搜索PROCINFO时找到了一个有效值列表,并进入了GNU Awk用户手册页面:https://www.gnu.org/software/gawk/manual/html_node/Controlling-Scanning.html

此页面列出了以下形式的选项:@{ind|val}_{num|type|str}_{asc|desc},其中:

  • ind按键(索引)排序,val按值排序。
  • num按数字排序,str按字符串排序,type按分配类型排序。
  • asc表示升序,desc表示降序。

我只是简单地使用了:

PROCINFO["sorted_in"] = "@val_num_desc"
for (i in map) print i, map[i]

输出结果按值的降序排序。


请注意,这仅适用于 gawk - PROCINFO 对于 awk 本身并不是特殊的东西。 - Eugene Pakhomov

9
请注意,asort()asorti()是特定于gawk的,对于awk来说是未知的。对于纯awk,您可以自己编写sort()或从其他地方获取一个。

7

以下内容直接摘自文档

 populate the array data
 # copy indices
 j = 1
 for (i in data) {
     ind[j] = i    # index value becomes element value
     j++
 }
 n = asort(ind)    # index values are now sorted
 for (i = 1; i <= n; i++) {
     do something with ind[i]           Work with sorted indices directly
     ...
     do something with data[ind[i]]     Access original array via sorted indices
 }

注意,这个解决方案存在缺陷,因为它最终会丢失原始数组中具有相同值的键。来自另一个线程的已接受解决方案有一个解决方法:https://dev59.com/u2435IYBdhLWcg3wkA5e#5345056 - haridsv
2
@haridsv 不,我不这么认为。这个问题是关于按键排序,而不是值排序,同一个键不能有两个值,所以这里没有问题。你指向的另一个问题是关于按值排序(这些值确实可能不都是不同的),所以如果你尝试使用这段代码进行排序,那就会有问题。但是,如果你按照它的写作目的使用它,那么它就没有缺陷。 - Cascabel
1
抱歉,我误读了索引代码,将键/值“翻转”,但在重新阅读后,我注意到您正在使用不断增加的数字作为索引,而不是原始值。感谢您回复并澄清。 - haridsv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接