5

次の形式の2つのログファイル(input.logおよび)があるとします。output.log

2012-01-16T12:00:00 12345678

最初のフィールドは処理タイムスタンプで、2番目のフィールドは一意のIDです。私は見つけようとしています:

  1. そのinput.logIDに対応するレコードがないレコードoutput.log
  2. input.logそのIDのレコードが含まれているがタイムスタンプの差が5秒を超えるレコード

MySQLを使用した回避策がありますが、理想的にはデータベースコンポーネントを削除し、シェルスクリプトで処理したいと思います。

IDが含まれているinput.log場合、列が追加されたの行を返す次のものがあります。output.log

join -a1 -j2 -o 0 1.1 2.1 <(sort -k2,2 input.log) <(sort -k2,2 output.log)

出力例:

10111 2012-01-16T10:00:00 2012-01-16T10:00:04
11562 2012-01-16T11:00:00 2012-01-16T11:00:10
97554 2012-01-16T09:00:00

主な質問

この情報を入手したので、2つのタイムスタンプの差を計算し、5秒以上離れたタイムスタンプを破棄するにはどうすればよいですか?ISO 8601タイムスタンプをdate(具体的にはT)で処理する際にいくつかの問題が発生し、より良い方法があるはずだと思いました。

二次質問

awkたとえば、アプローチ全体を1つのスクリプトに作り直す方法はありますか?複数のファイルを処理し、出力条件に対して正しい不等式を設定するという私の知識が、ここでの制限要因でした。したがって、上記のアプローチです。

4

3 に答える 3

4

あなたが持っているならGNU awk、あなたはこのようなことを試すことができます-

gawk '
NR==FNR{a[$2]=$1;next} 
!($2 in a) {print $2,$1; next} 
($2 in a) {
  "date +%s -d " $1 | getline var1;
  "date +%s -d " a[$2] | getline var2;
  var3 = var2 - var1;
  if (var3 > 4) print $2, $1, a[$2]
}' output.log input.log

テスト:

[jaypal:~/Temp] cat input.log 
2012-01-16T09:00:00 9
2012-01-16T10:00:00 10
2012-01-16T11:00:00 11

[jaypal:~/Temp] cat output.log 
2012-01-16T10:00:04 10
2012-01-16T11:00:10 11
2012-01-16T12:00:00 12

[jaypal:~/Temp] gawk '
NR==FNR{a[$2]=$1;next} 
!($2 in a) {print $2,$1; next} 
($2 in a) {"date +%s -d " $1 | getline var1; "date +%s -d " a[$2] | getline var2;var3=var2-var1;if (var3>4) print $2,$1,a[$2] }' output.log input.log
9 2012-01-16T09:00:00
11 2012-01-16T11:00:00 2012-01-16T11:00:10

説明:

  • NR==FNR{a[$2]=$1;next}

まず、output.logファイルの最初のフィールドを2番目のフィールドでインデックス付けされた配列に格納することから始めます。next他のpattern{action}ステートメントが実行されないようにするために使用します。を使用NR==FNRすると、output.logファイルを完全に丸呑みすることができます。

  • !($2 in a) {print $2,$1; next}

output.logファイルが完成したら。input.logファイルから始めます。input.logファイルに存在する2番目のフィールドが配列(つまり、output.logファイル)に存在しないかどうかを確認します。見つかった場合は印刷します。これらのフィールドをすべて印刷するまで、このアクションを続行します。

  • ($2 in a) {"date +%s -d " $1 | getline var1; "date +%s -d " a[$2] | getline var2; var3=var2-var1; if (var3 > 4) print $2,$1,a[$2] }

ここでは、両方のファイル存在するフィールドを探します。これらのフィールドを見つけたら、ロジックを入力して差を計算する必要があります。systemコマンドを使用して日付を検索します。現在、システムコマンドはデフォルトでSTDOUTに出力され、それらを制御することはできません。したがって、出力をパイプ処理し、関数を使用して出力をキャプチャawk getlineし、変数(var1およびvar2)に格納します。両方の日付が変数に格納されたら、差を取り、var3に格納します。var3が4より大きいことがわかった場合は、希望の形式で出力します。

于 2012-01-17T07:34:18.850 に答える
2

これが私が行った解決策です:

cat input.log
2012-01-16T09:00:00 9
2012-01-16T10:00:00 10
2012-01-16T11:00:00 11

cat output.log
2012-01-16T10:00:04 10
2012-01-16T11:00:10 11
2012-01-16T12:00:00 12

sort -k2,2 input.log > input.sort
sort -k2,2 output.log > output.sort

join -a1 -j2 -o 0 1.1 2.1 input.sort output.sort | while read id i o; do
    if [ -n "$o" ]; then
        ot=$(date +%s -d "${o/T/ }")
        it=$(date +%s -d "${i/T/ }")
        [[ $it+5 -lt $ot ]] && echo $id $i $o
    else echo $id $i
    fi
done
11 2012-01-16T11:00:00 2012-01-16T11:00:10
9 2012-01-16T09:00:00
于 2012-01-17T02:47:45.090 に答える
-1
t1=2012-01-16T10:00:00
t2=2012-01-16T10:00:04
echo $(($(date -d $t1 +%s)-$(date -d $t2 +%s)))
-4
于 2012-01-17T03:01:05.517 に答える