【问题标题】:Sorting array in shell using awk使用 awk 在 shell 中对数组进行排序
【发布时间】:2015-07-02 00:15:58
【问题描述】:

我需要按降序对该文件进行排序,以避免重复

Bob 5 404
Mike 3 404
Bob 19 404
Bob 78 404
Mike 93 404
Joe 7 404

所以我的结果应该是

Bob 102
Mike 96
Joe 7

我现在拥有的是这个

awk '{if($3 == 404) arr[$1]+=$2}END{for(i in arr)print i, arr[i]}' file

我知道有sort -d,但是我需要如何在awk中使用它?

更新

awk 'BEGIN{FS=" "}{if($9 == 404) arr[$1]+=1}END{for(i in arr) print arr[i] | sort -k2nr }' input > output

我得到了这个结果

sh: 0:  not found

我的输出文件现在是空的。

【问题讨论】:

  • 唯一键相对“有限”吗?
  • 如果您使用gawk,您可以访问asort() 函数。
  • 这不仅仅是排序。您正在聚合具有重复键的记录,而不是避免它们。
  • BEGIN{FS=" "} 不是必需的。您需要将+=1 替换为+=$2。将输出通过管道传送到 sort -k2nr 以按相反的数字顺序排序。
  • @JonathanLeffler:好建议,但要确保按第二列进行排序(尽管在 this 中没有区别例),应该是-k2,2nr

标签: arrays shell sorting unix awk


【解决方案1】:

Reuben L.'s answer 包含正确的指针,但没有说明完整的解决方案:


POSIX 兼容的解决方案详细说明:

您需要将awk 的输出管道sort 实用程序,awk 之外

awk '{ if($3 == 404) arr[$1]+=$2 } END{ for (i in arr) print i, arr[i] }' input |
  sort -rn -k2,2 > output

注意sort 命令的细节:

  • -r 执行反向排序
  • -n 执行数字排序
  • -k2,2 按第二个空格分隔的字段排序
    • 相比之下,仅指定-k2 将从第二个字段到行的其余部分排序开始 - 在这里没有区别,因为第二个字段是 last 字段,但一般来说它是一个重要的区别。

请注意,使用非标准的-V 选项进行数字排序确实没有任何好处,因为-n 就可以了; -V的真正目的是进行version-number排序。

请注意,您可以在您的awk 脚本中包含sort 命令 - for(i in arr)print i, arr[i] | "sort -nr -k2,2" - 请注意" 周围的@987654338 @ 命令 - 但是这样做没有什么好处


GNU awk asort() 解决方案 详细说明:

gawk '
  { if ($3 == 404) arr[$1]+=$2 } # build array
  END{
    for (k in arr) { amap[arr[k]] = k }   # create value-to-key(!) map
    asort(arr, asorted, "@val_num_desc")  # sort values numerically, in descending order
    # print in sort order
    for (i=1; i<=length(asorted); ++i) print amap[asorted[i]], asorted[i]
  }
' input > output

如您所见,这使解决方案复杂化,因为必须创建 2 个额外的数组

  • for (k in arr) { amap[arr[k]] = k }amap 中创建原始数组的“逆”:它使用原始数组的 values 作为 keys 和对应的 keys em> 作为
  • asort(arr, asorted, "@val_num_desc") 然后将原始数组按其 以数字降序排列 ("@val_num_desc") 并将结果存储在新数组 asorted 中。
    • 请注意,原来的在这个过程中丢失asorted键现在是反映排序顺序的数字索引。
  • for (i=1; i&lt;=length(asorted); ++i) print amap[asorted[i]], asorted[i] 然后按顺序数字索引枚举asorted,这会产生所需的排序顺序; amap[asorted[i]] 从原始数组中返回匹配键(例如,Bob)以获取手头的值。

【讨论】:

    【解决方案2】:

    两种可能的解决方案:

    1. 使用gawk和内置的asort()asorti()函数

    2. 将 awk 命令的输出通过管道传输到 sort -k2 -Vr。这将按第二列降序排序。

    注意:-V 标志是非标准的,可用于 GNU sort。归功于 Jonathan Leffler

    【讨论】:

    • 数字排序需要-k2n;否则,9 将出现在 89 之前。
    • 哦;嗯……我想是的。这不是一个标准选项——你应该指出它只适用于 GNU sort(例如,它不适用于 BSD/Mac OS X sort)。
    • @JonathanLeffler:奇怪的是,OSX sort 实用程序 GNU sort - 它只是太旧了支持-V(从OSX 10.10开始,它的版本是5.93(!),而Ubuntu 14.04上的版本是8.21)。相比之下,sort 的真正 BSD 版本确实实现了-V,至少从2.3 开始(例如,在 FreeBSD 10 上)。
    猜你喜欢
    • 1970-01-01
    • 2011-07-17
    • 2010-09-11
    • 2011-01-28
    • 2014-05-05
    • 2015-05-25
    • 1970-01-01
    • 2013-06-03
    • 2015-05-22
    相关资源
    最近更新 更多