質問
次のようながあります:
I, [2009-03-04T15:03:25.502546 #17925] INFO -- : [8541, 931, 0, 0]
I, [2009-03-04T15:03:26.094855 #17925] INFO -- : [8545, 6678, 0, 0]
I, [2009-03-04T15:03:26.353079 #17925] INFO -- : [5448, 1598, 185, 0]
I, [2009-03-04T15:03:26.360148 #17925] INFO -- : [8555, 1747, 0, 0]
I, [2009-03-04T15:03:26.367523 #17925] INFO -- : [7630, 278, 0, 0]
I, [2009-03-04T15:03:26.375845 #17925] INFO -- : [7640, 286, 0, 0]
I, [2009-03-04T15:03:26.562425 #17925] INFO -- : [5721, 896, 0, 0]
I, [2009-03-04T15:03:30.951336 #17925] INFO -- : [8551, 4752, 1587, 1]
I, [2009-03-04T15:03:30.960007 #17925] INFO -- : [5709, 5295, 0, 0]
I, [2009-03-04T15:03:30.966612 #17925] INFO -- : [7252, 4928, 0, 0]
I, [2009-03-04T15:03:30.974251 #17925] INFO -- : [8561, 4883, 1, 0]
I, [2009-03-04T15:03:31.230426 #17925] INFO -- : [8563, 3866, 250, 0]
I, [2009-03-04T15:03:31.236830 #17925] INFO -- : [8567, 4122, 0, 0]
I, [2009-03-04T15:03:32.056901 #17925] INFO -- : [5696, 5902, 526, 1]
I, [2009-03-04T15:03:32.086004 #17925] INFO -- : [5805, 793, 0, 0]
I, [2009-03-04T15:03:32.110039 #17925] INFO -- : [5786, 818, 0, 0]
I, [2009-03-04T15:03:32.131433 #17925] INFO -- : [5777, 840, 0, 0]
かっこ内の2番目と3番目のフィールドの平均を計算するシェルスクリプトを作成したい(最後の例では 840
と 0
)。さらに難しい質問:最後のフィールドが 0
でない場合にのみ、3番目のフィールドの平均を取得することは可能ですか?
Ruby
または別の言語を使用してスクリプトを作成できることは知っていますが、 Bash
でそれを行いたいです。リソースに関する適切な提案や、このようなスクリプトの作成方法に関するヒントが役立ちます。
解決
StackOverflowを試すようになったという理由だけで、ここにもIMで貼り付けた返信を投稿します:)
# replace $2 with the column you want to avg;
awk '{ print $2 }' | perl -ne 'END{ printf "%.2f\n", $total/$n }; chomp; $total+= StackOverflowを試すようになったという理由だけで、ここにもIMで貼り付けた返信を投稿します:)
<*>; $n++' < log
他のヒント
bash
および awk
を使用:
catファイル| sed -ne 's:^。* INFO。* \ [\([0-9、] * \)\] [\ r] * $:\ 1:p' | awk -F '*、*' '{sum2 + = $ 2; sum3 + = $ 3} END {if(NR&gt; 0)printf&quot; avg2 =%。2f、avg3 =%。2f \ n&quot ;, sum2 / NR、sum3 / NR} '
サンプル出力(元のデータ用):
avg2 = 2859.59、avg3 = 149.94
もちろん、 cat
を使用する必要はありません。読みやすくするためと、パイプから入力データを取得できることを示すために含まれています。既存のファイルを操作する必要がある場合は、 sed -ne '...' fileを実行します| ...
直接。
編集
gawk
(GNU awk)にアクセスできる場合、次のように sed
の必要性を排除できます。
catファイル| gawk '{if(match($ 0、/.*INFO.*\[([0-9、] *)\] [\ r] * $ /、a)){cnt ++; split(a [1]、b、/ *、* /); sum2 + = b [2]; sum3 + = b [3]}} END {if(cnt&gt; 0)printf&quot; avg2 =%。2f、avg3 =%。2f \ n&quot ;, sum2 / cnt、sum3 / cnt} '
同じコメント。 cat
を適用します。
ちょっとした説明:
-
sed
は、正規表現に一致する行(-n ...:p
の組み合わせ)のみを出力します(INFOの後に数字、スペース、行末の角括弧の間のコンマ。末尾のスペースとCRを許可します。そのような行が一致する場合は、印刷する前に、角括弧(\ 1
、正規表現の\(... \)
の間に対応するもの)の間のみを保持します(:p
)- sedは、
8541、931、0、0
のような行を出力します
- sedは、
-
awk
は、0個以上のスペースで囲まれたコンマ(-F '*、*'
)をフィールド区切り記号として使用します。$ 1
は最初の列(8541など)に対応し、$ 2
は2番目の列などに対応します。欠落している列は値0
としてカウントされます- 最後に、
awk
はアキュムレータsum2
などを処理されたレコードの数NR
で除算します
- 最後に、
-
gawk
はすべてをワンショットで実行します。最初に、各行が前の例でsed
に渡された同じ正規表現と一致するかどうかをテストします(ただし、sed
とは異なり、awk
は領域または関心を区切る丸括弧で囲まれた\
)。行が一致する場合、丸括弧の間にあるものはa [1]になります。a[1]は、同じセパレータ(任意の数のスペースで囲まれたコンマ)を使用して分割し、それを使用して累積します。NR
を使用し続ける代わりにcnt
を導入しました。処理されるレコードの数NR
は実際の関連レコードの数(cnt
)すべての行がINFO ... [... comma-separated-numbers ...]
の形式ではない場合、sedの場合はそうではありません
。sed
はawk
に渡されるすべての行が関連することを保証したため、| awk
nawk または / usr / xpg4 / bin / awk を Solaris で使用します。
awk -F'[],]' 'END {
print s/NR, t/ct
}
{
s += $(NF-3)
if ($(NF-1)) {
t += $(NF-2)
ct++
}
}' infile
Pythonを使用
logfile= open( "somelogfile.log", "r" )
sum2, count2= 0, 0
sum3, count3= 0, 0
for line in logfile:
# find right-most brackets
_, bracket, fieldtext = line.rpartition('[')
datatext, bracket, _ = fieldtext.partition(']')
# split fields and convert to integers
data = map( int, datatext.split(',') )
# compute sums and counts
sum2 += data[1]
count2 += 1
if data[3] != 0:
sum3 += data[2]
count3 += 1
logfile.close()
print sum2, count2, float(sum2)/count2
print sum3, count3, float(sum3)/count3