Unix实用程序,对保存条目下的数据求和

时间:2014-04-14 03:39:44

标签: unix command-line awk gawk

我想问这个小问题:

所以我有一个名为"quest"的文件,其中包含:

  

Tom 100 John 10 Tom 100

如何使用awk输出如下内容:

  

Tom 200

我很感激你的帮助。我试着在网上查询,但我不确定我在寻找什么。提前谢谢!!

我知道如何使用正则表达式/Tom/grep条目,但我不知道如何从那里继续。

5 个答案:

答案 0 :(得分:1)

您可以尝试以下内容:

$ awk '{
for(i=1; i<=NF; i+=2)
    names[$i] = ((names[$i]) ? names[$i]+$(i+1) : $(i+1))
}
END{
    for (name in names) print name, names[name]
}' quest
Tom 200
John 10

您基本上遍历字段,为所有奇数字段创建键,并为它们分配偶数字段的值。如果密钥已存在,则只需添加到现有值。

这要求您的文件格式在奇数字段(例如,1,3,5等等)上具有名称,在偶数字段上具有值(例如,2,4,6等等)。

END块中,您只需打印整个数组内容。

答案 1 :(得分:1)

我猜你需要计算所有用户&#39;标记,不仅Tom,这里是代码:

xargs -n2 < file|awk '{a[$1]+=$2}END{for (i in a) print i,a[i]}'

Tom 200
John 10

和awk的单行

awk '{for (i=1;i<=NF;i+=2) a[$i]+=$(i+1)}END{for (i in a) print i,a[i]}' file

Tom 200
John 10

答案 2 :(得分:0)

$ echo 'Tom 100 John 10 Tom 100' | grep -o '[0-9]*' | paste -sd+ | bc
210

grep -o '[0-9]*'生成

100
10
100

paste -sd+生成

100+10+100

bc计算结果。

但是,这仅适用于小输入,因为bc的输入大小有限制。

在这种情况下,您可以使用awk '{s+=$0}END{print s}'代替paste -sd+ | bc

但请注意GNU Awk将所有数字视为浮点数,当数字过大时会产生不准确的结果。

答案 3 :(得分:0)

awk '/Tom/{
     for(i=1;i<=NF;i++)
     if($i=="Tom")s+=$(i+1);
     print "Tom",s;s=0}' your_file

Test

答案 4 :(得分:-1)

这是在awk(无循环)中执行此操作的方法:

awk -v RS=" " '{n=$1;getline;a[n]+=$1} END {for (i in a) print i,a[i]}' quest
Tom 200
John 10

如果有多条这样的行

cat quest
Tom 100 John 10 Tom 100
Paul 20 Tom 40 John 10

然后使用gnu awk执行此操作:

awk -v RS=" |\n" '{n=$1;getline;a[n]+=$1} END {for (i in a) print i,a[i]}' quest
Paul 20
Tom 240
John 20

如果您不喜欢getline

awk -v RS=" |\n" 'NR%2 {n=$1;next}{a[n]+=$1} END {for (i in a) print i,a[i]}' quest