質問

次のようながあります:

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
    • のような行を出力します
  • 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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top