コマンドを複数回実行して、提供された複数のデータポイントの平均を調べています。この特別なケースでは、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
期間あたりの出力行が4行、期間がn個の場合は、同じフィールドに一致するすべての行を追加したいと思います。したがって、すべての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
と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] }'