合并第一列的结果然后总结第二列以列出第一列中每个条目的总计

我是Bash的新手,所以请在这里忍受我。

我有一个由另一个软件(我无法控制)转储的文本文件列出每个用户访问某些资源的次数,如下所示:

吉姆109
鲍勃94
约翰92
肖恩91
马克85
理查德84
吉姆79
鲍勃70
约翰67
肖恩62
马克59
理查德58
吉姆57
鲍勃55
约翰49
肖恩48
马克46
 。
 。
 。

我的目标是获得这样的输出。

吉姆[吉姆总计]
鲍勃[鲍勃总数]
约翰[约翰的总数]

等等。

每次我在软件中运行查询时,名称都会改变,所以静态search每个名称,然后通过wc进行pipe道操作并没有帮助。

Solutions Collecting From Web of "合并第一列的结果然后总结第二列以列出第一列中每个条目的总计"

这听起来像是awk的工作:)将程序的输出传递给下面的awk脚本:

 your_program | awk '{a[$1]+=$2}END{for(name in a)print name " " a[name]}' 

输出:

 Sean 201 Bob 219 Jim 245 Mark 190 Richard 142 John 208 

awk脚本本身可以用这种格式更好地解释:

 # executed on each line { # 'a' is an array. It will be initialized # as an empty array by awk on it's first usage # '$1' contains the first column - the name # '$2' contains the second column - the amount # # on every line the total score of 'name' # will be incremented by 'amount' a[$1]+=$2 } # executed at the end of input END{ # print every name and its score for(name in a)print name " " a[name] } 

请注意,要获得按分数排序的输出,可以添加另一个管道来sort -r -k2-r -k2按相反的顺序排列第二列:

 your_program | awk '{a[$1]+=$2}END{for(n in a)print n" "a[n]}' | sort -r -k2 

输出:

 Jim 245 Bob 219 John 208 Sean 201 Mark 190 Richard 142 

纯粹的Bash:

 declare -A result # an associative array while read name value; do ((result[$name]+=value)) done < "$infile" for name in ${!result[*]}; do printf "%-10s%10d\n" $name ${result[$name]} done 

如果第一个“完成”没有从输入文件重定向,则该脚本可以与管道一起使用:

 your_program | ./script.sh 

并对输出进行排序

 your_program | ./script.sh | sort 

输出:

 Bob 219 Richard 142 Jim 245 Mark 190 John 208 Sean 201 

GNU数据 datamash

 datamash -W -s -g1 sum 2 < input.txt 

输出:

 Bob 219 Jim 245 John 208 Mark 190 Richard 142 Sean 201