按计数分组的bash命令

时间:2017-08-16 09:19:59

标签: bash shell awk

我有以下格式的文件

abc|1
def|2
abc|8
def|3
abc|5
xyz|3

我需要在第一列中按这些单词进行分组,并将第二列的值相加。例如,此文件的输出应为

abc|14
def|5
xyz|3

说明:word" abc"的相应值通过添加这些数字,总和为14,输出变为" abc | 14"。同样,对于单词" def",相应的值为2和3.总结这些,最终输出为" def | 5"。

非常感谢您的帮助:)

我尝试了以下命令

awk -F "|" '{arr[$1]+=$2} END {for (i in arr) {print i"|"arr[i]}}' filename

我发现的另一个命令是

awk -F "," 'BEGIN { FS=OFS=SUBSEP=","}{arr[$1]+=$2 }END {for (i in arr) print i,arr[i]}' filename

两者都没有向我显示预期的结果。虽然我也对这些命令的工作也有疑问。

3 个答案:

答案 0 :(得分:3)

我将添加一个答案来修复您的排序问题,在您的Awk逻辑中,您不需要使用sort / uniq管道输出{ {1}},但在Awk本身处理。

参考GNU Awk Using Predefined Array Scanning Orders with gawk,您可以使用Awk变量(PROCINFO["sorted_in"]特定的)来控制gawk对最终输出进行排序的方式。

参考以下部分,

  

Awk   按索引按升序排序作为字符串进行比较;这是最基本的一种。 (在内部,数组索引始终是字符串,因此对于@ind_str_asc,索引为a[2*5] = 1而不是数字10。)

所以在10子句中的要求中使用它只需要做,

END

完整的命令,

END{PROCINFO["sorted_in"]="@ind_str_asc"; for (i in unique) print i,unique[i]}

答案 1 :(得分:2)

简称GNU datamash解决方案:

datamash -s -t\| -g1 sum 2 < filename

输出:

abc|14
def|5
xyz|3
  • -t\| - 字段分隔符

  • -g1 - 第1栏分组

  • sum 2 - 总结第二列的值

答案 2 :(得分:1)

 awk -F\| '{ arry[$1]+=$2 } END { asorti(arry,arry2);for (i in arry2) { print arry2[i]"|"arry[arry2[i]]} }' filename

您的初始解决方案应该与排序问题分开。使用asorti函数将索引从arry排序到arry2,然后在循环中处理它们。