ファイルの内容を取得するシェルスクリプト

ファイルの内容を取得するシェルスクリプト

「data_logs」というディレクトリに、毎分ログファイルを生成します。

ログファイル名:

abc.log.2019041607
abc.log.2019041608..

ログファイルの内容は次のとおりです。

R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1
R_MT|D:1234|ID:413|S:1

R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0
R_MT|D:1234|ID:413|S:0 
R_MT|D:1234|ID:413|S:0

k_MT|D:1234|ID:414|S:1
k_MT|D:1234|ID:414|S:1
k_MT|D:1235|ID:413|S:1
k_MT|D:1235|ID:413|S:1

私は実行されたときに過去5分間に生成されたファイル(最後に5つのファイル、毎分1つのファイルを生成)を探して、各ファイルを1つずつ開いて処理するシェルスクリプトを作成しています。つまり、出力を生成します。R_MT|D:1234|ID:413この組み合わせの 'Committed' 列に格納された 's' の合計数 0 と Uncommitted 列に格納された 's'=1 を含む txt ファイル

私のoutput.txtは次のようになります。

Type, Number,ID,submitted,notsubmitted
R_MT,D:1234,ID:413,5,10
R_MT,D:1234,ID:414,0,2
R_MT,D:1235,ID:413,0,2

私はこれを使用してコミットされた値とコミットされていない値を取得します。

zcat abc.log.2019041607.gz |grep "R_MT"|awk -F"|" '{print $2","$3","$4}'|sort|uniq -c
      5 D:1234,ID:413,S:0
     10 D:1234,ID:413,S:1
      2 D:1234,ID:414,S:1
      2 D:1235,ID:413,S:1

上記のコマンドを使用して数を取得しましたが、出力ファイルの「コミット済み」および「コミットされていない」フィールドに書き込むことができるように変数に割り当てる方法がわかりませんが、過去5分間のドキュメントですか?

助けてください、本当にありがとう!

答え1

input.logが入力のときにgawkで動作するこれがありますが、それでもawkとして理解しようとしています。

cat input.log |
 gawk -F"|" \
    #print the header
 'BEGIN{print"Type, Number,ID,submitted,notsubmitted"}
    #only work on non empty lines
 NF>0{ 
     #create an ID from the first three fields
    n=$1","$2","$3; 
        #everytime the ID pops up, increment subindex 1 or 2 depending on the value of field 4
        if($4=="S:1"){
            array[n][2]++}
        else{
            array[n][1]++}
}
     #print the final array
END{for(i in array){
       #if the value has never been seen declare it to be zero
        if(array[i][1]){
            m=array[i][1]}
        else {
            m=0}
        if(array[i][2]){
            n=array[i][2]}
        else {
            n=0}
    print i","m","n}
}'

答え2

過去5分以内に変更されたログファイルを見つけるには、たとえばfind

find data_logs/ -type f -name 'abc.log.*' -mmin -6

以下より少なく変更されたログファイルを見つけます。6数分前だけでも、ほとんどの場合、この程度で十分でした。正確なファイル変更時間が必要な場合は、次を使用します。

find data_logs/ -type f -name 'abc.log.*' \( -mmin -5 -o -mmin 5 \)

5分前または正確に5分前に変更されたファイルは見つかりません。

からman find

-mmin n
    File's data was last modified n minutes ago.

そして:

数値パラメータは次のように指定できます。

 +n     for greater than n,
 -n     for less than n,
  n     for exactly n.

答え3

クロスパブリッシュの問題https://stackoverflow.com/q/57377173/3220113保留されました。ここで許可された回答をコピーします。他の質問は削除できます。

ファイルの場合: まず、awkを使用してストリームを簡単に処理できるようにします(より良いパフォーマンスを得るためにすべてawkで実行できます)。

sed -nr 's/\|/,/g;s/(^R_MT,.*),S:([^ ]) *$/\1 \2/p' <(zcat abc.log.2019041607.gz)

結果(追加テストラインを追加した後)

R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 1
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:413 0
R_MT,D:1234,ID:414 1
R_MT,D:1234,ID:414 1
R_MT,D:1235,ID:413 1
R_MT,D:1235,ID:413 1

次に、配列aをフィールド名として使用してawkで計算します。

sed -nr 's/\|/,/g;s/(^R_MT,.*),S:([^ ]) *$/\1 \2/p' <(zcat abc.log.2019041607.gz) |
   awk '{a[$1]; if ($2>0) notsub[$1]++; else submit[$1]++;}
        END {for (i in a) print i "," submit[i]+0 "," notsub[i]+0;}
       '

5つのファイルの場合は、まず目的の結果を決定してください。各ファイルには異なる出力ファイルがあります。次のループを使用します。

while IFS= read -r filename; do
   ... <( zcat "${filename}") ...
done < <(find datalogs -type f -name "abc*" -mmin -5)

5つのファイルの結果が単一の合計に追加されます。

... <( find datalogs -type f -name "abc*" -mmin -5 -exec zcat {} \;) ...

答え4

必要な時間に基づいてファイルを簡単に見つけることができます。ただし、結果を得るには、awk次のように使用できます。

  awk -F\| '!/^\s*$/{if($4=="S:0"){Arr0[$1","$2","$3]+=1} else {Arr1[$1","$2","$3]+=1}}END{for(i in Arr1){print i,",",Arr0[i],",",Arr1[i]}}'

説明する:

  1. -F\|:|フィールド区切り文字として定義

  2. !/^\s*$/: 空行をスキップ

  3. if(Clause){Statement}else{statement}: 明らか

  4. END{...}:このブロックは、演算子がEOFに達すると実行されます。

関連情報