1

私は次のようなものを持っています:

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最後の例)。さらに難しい質問: 最後のフィールドが でない場合にのみ、3 番目のフィールドの平均を取得することは可能0ですか?

または別の言語を使用してスクリプトを作成できることはわかっていRubyますが、.NET で作成したいと考えていBashます。このようなスクリプトを作成する方法に関するリソースやヒントに関する良い提案があれば役立ちます。

4

4 に答える 4

6

使用bashawk

cat file | sed -ne 's:^.*INFO.*\[\([0-9, ]*\)\][ \r]*$:\1:p' | awk -F ' *, *' '{ sum2 += $2 ; sum3 += $3 } END { if (NR>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/NR, sum3/NR }'

サンプル出力(元のデータ用):

avg2=2859.59, avg3=149.94

もちろん、を使用する必要はありません。cat読みやすくするため、および入力データが任意のパイプから取得できるという事実を説明するために含まれています。既存のファイルを操作する必要がある場合は、sed -ne '...' file | ...直接実行してください。


編集

(GNU awk)にアクセスできる場合は、次のようgawkにする必要がありません。sed

cat file | gawk '{ if(match($0, /.*INFO.*\[([0-9, ]*)\][ \r]*$/, a)) { cnt++; split(a[1], b, / *, */); sum2+=b[2]; sum3+=b[3] } } END { if (cnt>0) printf "avg2=%.2f, avg3=%.2f\n", sum2/cnt, sum3/cnt }'

同じ発言再。cat申し込み。

少し説明:

  • sed正規表現に一致する行(組み合わせ)のみを出力します(-n ... :pINFOを含む行の後に、行末の角かっこで囲まれた数字、スペース、コンマの任意の組み合わせ。末尾のスペースとCRを使用できます)。そのような行が一致する場合は、印刷する前に角かっこ(正規表現\1の間にあるものに対応)の間にあるものだけを保持してください( ) \(...\):p
    • sedは、次のような行を出力します。8541, 931, 0, 0
  • awk-F ' *, *'フィールド区切り文字として0個以上のスペース()で囲まれたコンマを使用します。$1最初の列(例:8541)、$22番目の列などに対応します。欠落している列は値としてカウントされます0
    • 最後にawk、アキュムレータsum2などを処理されたレコードの数で除算します。NR
  • gawkすべてをワンショットで実行します。最初に、各行が前の例で渡されたのと同じ正規表現に一致するかどうかをテストしますsed(ただし、とは異なりsed、領域または関心を区切る丸括弧awkは必要ありません)。\行が一致する場合、丸括弧の間にあるものはa [1]になり、同じ区切り文字(任意の数のスペースで囲まれたコンマ)を使用して分割し、それを使用して累積します。すべての行がの形式ではない場合、処理されるレコードの数が実際の関連レコードの数()よりも多くなる可能性があるため、cnt使用を継続する代わりに導入しました。これは、すべての行がに渡されることが保証されているため、そうではありませんでした。NRNRcntINFO ... [...comma-separated-numbers...]sed|awksedawk関連していた。
于 2009-03-04T23:16:29.163 に答える
1

StackOverflow を試してみるという理由だけで、ここにも IM で貼り付けた返信を投稿します :)

# replace $2 with the column you want to avg; 
awk '{ print $2 }' | perl -ne 'END{ printf "%.2f\n", $total/$n }; chomp; $total+= $_; $n++' < log
于 2009-03-05T00:36:05.227 に答える
0

Solarisでは nawkまたは/ usr/xpg4/bin/awkを使用します。

awk -F'[],]' 'END { 
  print s/NR, t/ct 
  }  
{ 
  s += $(NF-3) 
  if ($(NF-1)) {
    t += $(NF-2)
    ct++
    }
  }' infile
于 2009-03-05T11:41:17.127 に答える
0

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
于 2009-03-05T11:49:09.993 に答える