我有一个文件如下:
Bitrate ASNUM TotalBytes DownloadTime NumberCount
280000 2856 61454 12
280000 2856 61428 14
1179968 2856 309430 11
1179968 4156 309200 15
4864960 2856 997962 193
4864960 2856 1115576 300
4864960 2856 997962 116
我需要根据前 2 列(即比特率和 ASNUM)合并行,并将与它们相对应的总字节数和下载时间字段相加。
结果输出应如下所示:
Bitrate ASNUM TotalBytes DownloadTime NumberCount
280000 2856 122882 26 2
1179968 2856 309430 11 1
1179968 4156 309200 15 1
4864960 2856 3111500 609 3
其中附加列 NumberCount 指示出现的次数。
您能否帮助我实现可以实现此功能的代码?
答案1
这是使用 awk 的解决方案:
awk -F " " '
NR==1 {print; next}
NF {a[$1" "$2]+=$3; b[$1" "$2]+=$4; c[$1" "$2]++}
END {for(i in a)print i, a[i], b[i], c[i]}
' file
--> inputFile 应该位于运行命令的目录中
--> -F " " 认为单个空格作为分隔符
--> NR==1{print;next} 打印要输出的标题并跳过它
--> 数组 a[$1" "$2] 考虑第一列值和第二列值的分组依据。数组 b 和 c 相同。
--> += 运算符根据数组的分组依据对所需列进行求和
--> 与数组 c 一起使用的 ++ 运算符存储 group by 的计数
--> 最后一个“for”循环用于打印结果以输出
答案2
GNU 数据混合是为此类任务而设计的 - 例如
datamash -WH -g 1,2 sum 3,4 count 4
或者更详细地说
datamash --whitespace --headers \
groupby Bitrate,ASNUM sum TotalBytes,DownloadTime count DownloadTime
(您为 指定哪个非分组字段并不重要count
)。
您的情况因空白行而稍微复杂 - 但您可以简单地在之前将它们删除并在之后重新添加它们,例如
sed '/^$/d' file | datamash -WH -g 1,2 sum 3,4 count 4 | column -t | sed G
GroupBy(Bitrate) GroupBy(ASNUM) sum(TotalBytes) sum(DownloadTime) count(DownloadTime)
280000 2856 122882 26 2
1179968 2856 309430 11 1
1179968 4156 309200 15 1
4864960 2856 3111500 609 3