行フィールドに数値を追加する awk メソッド

行フィールドに数値を追加する awk メソッド

現在のデータ:

blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=92 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=92 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=14 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=93 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=93 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=92 Auto_save__of__retention__data__completed=1 Warning___Return=8 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=73 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=99 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=93 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=75 Auto_save__of__retention__data__completed=1 Warning___Return=38 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=21 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=12 Auto_save__of__retention__data__completed=1 Warning___Return=28 PASSIVE__SERVICE__CHECK_=23 ,1026--1313,1[/CODE]

上記の各行のフィールドは「カンマ」で区切られます。私が興味を持っているのはフィールド9です。

フィールド 9 には複数の値があります。

私がしたいことは2つの部分です。

  1. すべての値を加算できます。特定モードデータファイルのすべての行で。たとえば、データファイルのすべての行の「on__host」の合計値を知りたい場合です。

  2. ログのすべての行にわたって行ごとにすべてのパターンのすべての値を合計する機能。

私は9番目のフィールドに1つの値しかない古いデータで作業しています。これは扱いやすいです。データは次のとおりです。

前のデータ

blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,53,1026--1313,1

私がしなければならないのは、すべての行の9番目のフィールドに値を追加することだけです。

awk -F, 'BEGIN{sum=0} {sum+=$9} END {print sum}' data.prev

この問題を解決したスクリプトは次のとおりです。

#!/bin/sh
Pattern=$1
if [ "${Pattern}" = "allpatterns" ] ; then
   awk should add up all the values in the 9th field of data in data.now
else
   if the user did not specify "allpatterns", then, awk should take the pattern name specified by the user and use that to decide which pattern to add up in the 9th field of all the lines.
    awk -F"," '$9 ~ /'${Pattern}'/ '{do awk magic}'  -- this is just an idea.
fi

このスクリプトは、すべてのUNIXシステムで実行されることが予想されます。私が使用するシェルは/bin/shまたは/bin/bashです。

要求の最初の部分でデータファイルのすべての行にあるすべてのパターンのすべての値を追加した場合、出力は数値の合計になるはずです。これは504(私が選択したランダム数)です。 )。

私の要求の2番目の部分で特定のパターンの値を追加した場合、出力はその特定のパターンの値の合計でなければなりません。つまり、「on__host=400」です。

答え1

以下は実行しやすい作業です(より実行しやすいperl作業はあまりありません)。awkperl

$ perl -F, -lae '$c{$1} += $2 while $F[8] =~ /(\S+)=(\d+)/g;
                 END {print "$_ => $c{$_}" for sort keys %c}' < file
Auto_save__of__retention__data__completed => 6
PASSIVE__SERVICE__CHECK_ => 288
SERVICE__ALERT_ => 306
Warning___Return => 278
Warning___The__results__of__service => 96
Warning___on__host => 463
on__host => 386

たとえば、値のみが必要な場合はブロックENDをに変更します。{print $c{on__host}}on__host

答え2

最初の部分では、次のことがうまくいくと思いました。

cat data.now | awk -F, '{print $9}' | sed 's/=/ /g' | awk '
    { 
        for (i = 1; i <= NF; i += 2) {
            a[$i]+=$(i+1); 
        }
    } 
    END {
        for (i in a) print i, "=", a[i]
    }'

このコードは次のような出力を生成します。

PASSIVE__SERVICE__CHECK_ = 288
Warning___Return = 278
Auto_save__of__retention__data__completed = 6
SERVICE__ALERT_ = 306
Warning___The__results__of__service = 96
on__host = 386
Warning___on__host = 463

ここで唯一の潜在的な問題は、順序が元のファイルの順序と異なることです。順序が重要な場合は、次のものを使用できます。

cat data.now | awk -F, '{print $9}' | sed 's/=/ /g' | awk '
    { 
        for (i = 1; i <= NF; i += 2) {
            a[$i]+=$(i+1); 
            b[i]=$i;
        }
    } 
    END {
        for (i in b) print b[i], "=", a[b[i]]
    }'

しかし、読むのはそれほど簡単ではありません。

2番目の質問の場合、これは最も短いまたは最も効率的な方法ではありませんが、合計を計算できると思います。

cat data.now | awk -F, '{print $9}' | 
    sed "s/.*\<${Pattern}=\([0-9]\+\).*/\1/g" | 
    awk '{s += $1} END {print s}'

答え3

空間的にsplitファイリング$9し、結果を繰り返してパターンを選択し、見つかった要素を見つけsplit=値を抽出できます。

awk -F, -v pat='^on__host=' '{
  n = split($9,a," "); 
  for(i=1;i<=n;i++) {
    if(a[i] ~ pat) {
      split(a[i],b,"="); 
      sum+=b[2]
    } 
  }
} 
END{print sum}
' data.now 

関連情報