关于awk(bash)的问题,要求对每个项目的值求和。输入文件如下:
item value
----------------
item1 8
item1 1
item1 5
item2 2
item2 8
item3 4
item3 7
item3 7
Timely Total xxx
item1 5
item1 4
item1 3
item2 4
item2 1
Timely Total 17
我的问题: 要对每个项目求和,我有代码:
awk '{a[$1]+=$2}END{for(i in a) print i, "has", a[i], "entries" }'
没关系,但是它会在所有Timelytotals中为所有item1的整个文件求和
我需要:Timely total1中item1的总和,Timely total1中item2的总和,Timely total1中item3的总和,然后 timely total2中item1的总和,Timely total2中item2的总和,Timely total2中item3的总和。 类似于更及时的总计。
答案 0 :(得分:3)
您还没有真正说出输出应该是什么样子,所以任何答案在某种程度上都是猜测。这是我的猜测。
script.awk
NR < 3 { print; next }
$1 == "Timely" {
for (a in sum)
{
print "Subtotal", a, sum[a]
}
print "Timely Total ", total
total = 0;
delete sum
next
}
$1 == "" { print; next }
{
sum[$1] += $2
total += $2
print
}
第一行打印两个标题行。
&#39;及时&#39;块打印累积的数据(假设有一些要打印)。对于显示的每个项目,它会打印相应的总和以及标识信息。然后它会打印一个“及时总计”&#39;整个街区。然后通过删除sum
数组并将total
归零来为统计数据清零,为下一组数据做好准备。
打印$1 == ""
块,否则忽略空行。
默认块累计项目和总和的总和并打印该行。
显然,如果您不想要各个数据行,则省略最后一个print
。同样清楚的是,你可以用你喜欢的任何格式打印小计(实际上是总数) - printf
函数在这里很有用。如果您不打印各行,则可能会跳过两个标题行而不是打印它们。可以进行无休止的调整,但在没有相反信息的情况下,我相信这提供了一个合理的答案,可以很容易地适应所需的输出格式。
需要注意的一点是:样本数据最终按顺序打印了项目小计,但这很可能是偶然而非保证的行为。如果重要的话,有办法解决这个问题。但是,有多种方法可以实现,GNU Awk内置了额外的功能,可以帮助其他Awk变体需要手动编码。
$ awk -f script.awk data
item value
----------------
item1 8
item1 1
item1 5
item2 2
item2 8
item3 4
item3 7
item3 7
Subtotal item1 14
Subtotal item2 10
Subtotal item3 18
Timely Total 42
item1 5
item1 4
item1 3
item2 4
item2 1
Subtotal item1 12
Subtotal item2 5
Timely Total 17
$
答案 1 :(得分:0)
祝贺一个详细的问题,并解释你想要完成的事情。一种方法是使用$ 1以外的东西作为关联数组的关键。由于在整个领域中没有任何东西看起来像一把钥匙,你可以保留一个计数器,看看你已经看过多少次&#34;及时&#34;之前并为每一个增加它。
$awk 'BEGIN {timely=1;} /^item[0-9]+/ {a[timely "-" $1]+=$2} /^Timely.*/ {timely+=1} END {for(i in a) print i,"has" ,a[i] " entries" }' < t | sort
1-item1 has 14 entries
1-item2 has 10 entries
1-item3 has 18 entries
2-item1 has 12 entries
2-item2 has 5 entries
关键部分是a[timely "-" $1]+=$2
,它将总数存储在单独的&#34;存储桶&#34;每次找到新的/^Timely.*/
时。