我正在研究对多次运行命令给出的多个数据点进行平均。在这种特殊情况下,我使用的是sysbench
工具套件。
此示例输入来自单次sysbench cpu <parameters>
运行;请记住,这将运行多次,因为我希望对某些结果进行平均:
CPU speed:
events per second: 827.81
General statistics:
total time: 30.0021s
total number of events: 44977
Latency (ms):
min: 2.01
avg: 4.93
max: 733.85
95th percentile: 12.98
sum: 228990.08
在我的示例脚本中
(for ((n=0;n<3;n++)); do
<command> | grep -i <data point lines>;
done) | awk '{ print $(NF) }'
我从每次运行中获取相关数据点并打印(作为我将使用的任何代码的占位符)下面每行的最后一个字段。这包含我需要使用的数字。我需要的是将每 n 个 $(NF) 加在一起,然后对它们进行平均,我已经可以概念化了。
让我们从这个例子中说,我想采取这些观点(目前通过 grep 但不关心实现)
events per second: 827.81
avg: 4.93
max: 733.85
95th percentile: 12.98
并从中获取最后一列(当前通过 awk '{ print $(NF) }')
827.81
4.93
733.85
12.98
假设每个周期和 n 个周期有 4 行输出,我想添加与同一字段匹配的所有行(因此所有 avg: 都被求和并平均,对于 max: 和其他统计数据也是如此。)
add lines 1/5/9/4n
2/6/10/4n
3/7/11/4n
4/8/12/4n
together
我正在尝试使用 awk (因为此代码将在多个 unix 系统上使用,并且 awk 是一个常见因素),但如果我使这个过于复杂并且有更好的替代方案,我很高兴听到它。
答案1
你可以获得一些东西关闭到你想要的:
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ { sum[$1] += $NF ; count[$1]++ };
END { for (i in sum) print i, sum[i]/count[i] }' input.[123]
95th:11.3133
avg:4.53
events:691.143
min:2.31
注意:input.1、input.2 和 input.3 是示例输入的副本,并稍微编辑了值。
另请注意:sub()
在脚本的第一行中使用以去除任何前导空格。由于 $0 已更改,因此会重新评估字段拆分,因此我们保证 $1 中有一个可用的(短)名称。我们并不真正关心它是什么,只关心它唯一标识我们从中提取值的记录类型。
不幸的是,因为它使用关联数组,所以输出的顺序是伪随机的(即您不能指望以任何特定顺序出现的元素)。为了获得一致的顺序,您可以使用sort
第一个输出字段,然后cut
仅获取值。
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ { sum[$1] += $NF ; count[$1]++ };
END { for (i in sum) print i, sum[i]/count[i] }' input.[123] |
sort -t: -k1,1 | cut -d: -f2
11.3133
4.53
691.143
2.31
如果您有 GNU awk,则可以使用该asorti()
函数对关联数组的索引进行排序,从而无需通过管道输入sort
and cut
。
$ awk -F'[: ]' -v OFS=: '{sub("^ *","")};
/^(events|avg|min|95th)/ {sum[$1] += $NF ; count[$1]++ };
END {
num=asorti(sum,idx);
for (i=1;i<=num;i++) print sum[idx[i]]/count[idx[i]]
}' input.[123]
11.3133
4.53
691.143
2.31
答案2
编写你的脚本如下:
{ for ((n=0; n<4; n++)); do <command>; done; } |\
awk -v t=$n 'i==t{ i=0 }
/(events per second|avg|max|95th percentile):/{ seen[++i]+=$NF/t }
END{ for(x in seen) print x, seen[x] }'