使用awk

时间:2017-02-03 12:26:11

标签: bash awk

我有一个具有以下结构的文件:

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

我知道cutuniq:直到现在我设法在第一列中找到重复值:

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循环地狱!);有没有办法找到第一列重复,加上它的第二列值并重写删除重复的行并打印第二列的结果总和?

5 个答案:

答案 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
$