長い変数文字列を含むログがあり、数値から最小、最大、平均を取得しようとしています。
文字列の例
date time from Time: 100 ms to status code:
date time Time: 1050 ms status code IP
date time IP Time: 2 ms status code destination
「Time:* ms」はすべての行で一定ですが、フィールドの位置は変わります。最大、最小、平均ミリ秒が必要です。
答え1
GNU awkの使用FPAT
(正規表現(文字列)は、gawkに正規表現に一致するテキストに基づいてフィールドを生成するように指示します。"):
awk -v FPAT='Time:[[:blank:][:digit:]]+ms' '
{ split($1, tmp); sum+=tmp[2] }
NR==1 { min=max=tmp[2] }
min>tmp[2]{ min=tmp[2] }
max<tmp[2]{ max=tmp[2] }
END{ print min, max, sum/NR }' infile
出力;
2 1050 384
答え2
これを行う1つの方法は、各行のすべてのフィールドを繰り返して「ms」のフィールド番号を取得し、そのフィールド番号から1を引くことです。これにより、その番号のフィールド番号が提供されます。数値が常にmsの前のフィールドである限り、これはうまくいきます(私の考えでは、これがあなたが言うものです)。
以下は、各番号を印刷する例です。
awk '{for(i-1;i<=NF;++i){if($i == "ms"){print $(i-1)}}}' filename
数値の最小値、最大値、平均を取得するには、もう少し作業を行う必要があります。
awk '
{for(i=1;i<=NF;++i){
if($i == "ms")
{
if(NR == 1)
{min=max=$(i-1)};
if($(i-1) > max)
{max=$(i-1)};
if($(i-1)<min)
{min=$(i-1)};
sum=sum+$(i-1);
count+=1;
}
}
}
END{
average=sum/count;
print "min: "min;
print "max: "max;
print "sum: "sum;
print "average: "average;
}
出力:
min: 2
max: 1050
sum: 1152
average: 384
答え3
そしてアッまず、各レコードでミリ秒を見つけて数値に変換し、累計を更新します。
awk '
p=match($0, /Time: [0-9]+ ms/){
sum += ms = substr($0,p+6,RLENGTH-9)+0
}
ms>max{max=ms}
min==""||ms<min{min=ms}
END{print min, max, sum/NR}
' file
出力
2 1050 384
答え4
注文する
最大値:
awk '{for(i=1;i<=NF;i++){if($i ~ /ms/){print $(i-1)}}}' filename| awk 'NR==1{sum=$1}($1 > sum){sum=$1}END {print sum}'
出力
1050
最小値:
awk '{for(i=1;i<=NF;i++){if($i ~ /ms/){print $(i-1)}}}' filename| awk 'NR==1{sum=$1}($1 < sum){sum=$1}END {print sum}'
出力
2