我有一个具有以下结构的文件:
1486113768 3656
1486113768 6280
1486113769 530912
1486113769 5629824
1486113770 5122176
1486113772 3565920
1486113772 530912
1486113773 9229920
1486113774 4020960
1486113774 4547928
我的目标是摆脱第一列中的重复值,将第二列中的值相加并使用新列值更新行:来自上面输入的工作输出将是:
1486113768 9936 # 3656 + 6280
1486113769 6160736 # 530912 + 5629824
1486113770 5122176 # ...
1486113772 4096832
1486113773 9229920
1486113774 8568888
我知道cut
,uniq
:直到现在我设法在第一列中找到重复值:
cut -d " " -f 1 file.log | uniq -d
1486113768
1486113769
1486113772
1486113774
实现目标是否有“尴尬的方式”?我知道它是非常强大和简洁的工具:我之前用过
awk '{print $2 " " $3 >> $1".log"}' log.txt
扫描log.txt中的所有行并创建一个名为$ 1的.log文件,并用$ 2和$ 3值填充它们,所有这些都在一个bash行中(到read
循环地狱!);有没有办法找到第一列重复,加上它的第二列值并重写删除重复的行并打印第二列的结果总和?
答案 0 :(得分:10)
使用Awk
,如下所示
awk '{ seen[$1] += $2 } END { for (i in seen) print i, seen[i] }' file1
1486113768 9936
1486113769 6160736
1486113770 5122176
1486113772 4096832
1486113773 9229920
1486113774 8568888
{seen[$1]+=$2}
创建一个哈希映射,其中$1
被视为索引值,而且总和仅针对文件中$1
的唯一项目递增。
答案 1 :(得分:3)
$ awk '$1!=p{ if (NR>1) print p, s; p=$1; s=0} {s+=$2} END{print p, s}' file
1486113768 9936
1486113769 6160736
1486113770 5122176
1486113772 4096832
1486113773 9229920
1486113774 8568888
以上几乎不使用任何内存(只需1个字符串和1个整数变量),并按照输入中显示的顺序打印输出。
我强烈建议你阅读Arnold Robbins的书“Effective Awk Programming,4th Edition”,如果你将要使用awk,那么你可以学习如何编写自己的脚本(和你一样)学习)所以你可以很好地理解其他人的脚本,将权利与错误的方法分开,给出2个脚本,根据一些特定的样本输入产生预期的输出。
答案 2 :(得分:3)
如果datamash没问题
$ datamash -t' ' -g 1 sum 2 < ip.txt
1486113768 9936
1486113769 6160736
1486113770 5122176
1486113772 4096832
1486113773 9229920
1486113774 8568888
-t' '
将空格设置为字段分隔符-g 1
group by 1st field sum 2
求和第二个字段值datamash -st' ' -g 1 sum 2
选项处理排序的-s
答案 3 :(得分:0)
假设您将许多日志文件的输出结果排在前十行,并将它们合并到一个文件中(并以“ sort”排序):
6
5
4
3
2
您还可以更改总和的顺序:
2142 /pathtofile1/00.jpg
2173 /pathtofile1/00.jpg
2100 /pathtofile1/00.jpg
2127 /pathtofile1/00.jpg
您将获得总计:
$ awk '{ seen[$2] += $1 } END { for (i in seen) print i, seen[i] }' top10s.txt | sort -k 2 -rn
答案 4 :(得分:0)
使用Perl
$ cat elmazzun.log
1486113768 3656
1486113768 6280
1486113769 530912
1486113769 5629824
1486113770 5122176
1486113772 3565920
1486113772 530912
1486113773 9229920
1486113774 4020960
1486113774 4547928
$ perl -lane ' $kv{$F[0]}+=$F[1];END { print "$_ $kv{$_}" for (sort keys %kv)}' elmazzun.log
1486113768 9936
1486113769 6160736
1486113770 5122176
1486113772 4096832
1486113773 9229920
1486113774 8568888
$