UNIXの大容量ログファイルから情報を取得する簡単な方法

UNIXの大容量ログファイルから情報を取得する簡単な方法

6GBのアプリケーションログファイルがあります。ログの形式は次のとおりです(省略)。

[...]
timestamp;hostname;sessionid-ABC;type=m
timestamp;hostname;sessionid-ABC;set_to_TRUE
[...]
timestamp;hostname;sessionid-HHH;type=m
timestamp;hostname;sessionid-HHH;set_to_FALSE
[...]
timestamp;hostname;sessionid-ZZZ;type=m
timestamp;hostname;sessionid-ZZZ;set_to_FALSE
[...]
timestamp;hostname;sessionid-WWW;type=s
timestamp;hostname;sessionid-WWW;set_to_TRUE

この2行に加えて、会議がたくさんあります。type=mに関連するすべてのセッションを見つける必要があります。set_to_TRUE

私の最初の試みは、すべてのsessionIDをgrepしてtype=mファイルに書き込むことでした。次に、大きなログファイルを繰り返し、ファイルの各行に対してgrepを実行します(1行につき1つのsessionID)。sessionID;set_to_TRUE

この方法は時間がかかります。誰もがこの問題を解決するためのより良いより速い方法についてのヒントを与えることができますか?

答え1

各セッションに対応するtypeand isまたはset_toTRUEある場合は、andスコープをFALSE使用してsed以下を実行できます。

sed '/type=m/,/set_to_/!d;/set_to_TRUE$/!d;s/.*\(sessionid-.*\);.*/\1/' infile

/type=m/,/set_to_/範囲に含まれていないすべての行が削除されます。また、範囲がで終わらない行を削除しますset_to_TRUEsessionid次に、残りの行(存在する場合)から抽出します。
または、

sed -n '/type=/h;/set_to_TRUE$/{
x;s/.*\(sessionid-.*\);type=m$/\1/p
}' infile

同じように印刷する必要があります。
後者は、一致する各行の保持バッファを上書きするように機能しますtype=
。次に、一致する各行でset_to_TRUEバッファを交換し、交換を試みます。つまり、sessionidで終わる行から抽出し、type=m成功すると結果を印刷しますp。それ以外の場合は自動印刷が無効になり、何も起こりません-n
上記は、行に末尾の空白がないと仮定しています。

答え2

次のawkコマンドを使用します。

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag)' infile.txt

2 つの sessionID が同じであり、前提条件が同じ場合は一致します。

timestamp;hostname;sessionid-ABC;set_to_TRUE

print $3上記は、行全体を印刷します。次のようにsessionIDのみを追加することで、必要な列のみを印刷できます。

awk -F";" '/type=m/{flag=$3;next} /set_to_TRUE/ && ($3==flag){print $3}' infile.txt

答え3

grepを使用すると簡単に実行できます。

grep -E "(type=|set_to_)" file.txt | grep -A 1 "type=m" | grep -B 1 "set_to_TRUE" > file1.txt &

背景に置き、一杯のコーヒーを飲み、作業を完了します。 「awk」または「sed」が速いかどうかはわかりません。 6GBはプレーンテキストを保存するには余りにも多くのスペースなので、何をしようとしても時間がかかります。

とにかくEnterキーを押すか、別のコマンドを入力すると、完了するとコンソールに表示されます。

[1]+  Done                    grep --color=auto -E '(type=|set_to_)' file.txt | grep --color=auto -A 1 "type=m" | grep --color=auto -B 1 "set_to_TRUE" > file1.txt

答え4

awk -F';' '/type=m/ { seen[$3]=1 };
           /set_to_TRUE/ && seen[$3] { print $3 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

これは次のようになります。αГsнιnの答えただし、単一変数(flag)を使用する代わりに、配列(seen)を使用して一致するセッションIDを追跡しますtype=m

type=mつまり、任意のセッションラインターゲティングとそのセッションラインターゲティングとの間に別のセッションの他のラインがあってもtype=m機能しますset_to_

スクリプトのメモリー要件を最小限に抑えるために、一致または見つかった直後に指定されたseenセッション ID の配列要素を削除します。set_to_TRUEset_to_FALSE

注:上記のスクリプトは一致するセッションIDのみを印刷します。実際のtype=m合計行を印刷するには、set_to_TRUEawkスクリプトは次のようになります。

awk -F';' '/type=m/ { seen[$3]=$0 };
           /set_to_TRUE/ && seen[$3] { print seen[$3]"\n"$0 ; delete seen[$3] };
           /set_to_FALSE/ && seen[$3] { delete seen[$3] }' logfile.txt

これにより、より多くのメモリを使用する可能性があります。入力ライン全体を配列に格納するには、整数を格納するよりも多くのRAMが必要です。

注2:このスクリプトはセッションIDが一意であると想定しています。たとえば、異なるホスト名(フィールド2)が同じセッションIDを生成できる場合は、次のようにします。

awk -F';' '/type=m/ { seen[$3$2]=1 };
           /set_to_TRUE/ && seen[$3$2] { print $3 ; delete seen[$3$2] };
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

または

awk -F';' '/type=m/ { seen[$3$2]=$0 };
           /set_to_TRUE/ && seen[$3$2] {print seen[$3$2]"\n"$0;delete seen[$3$2]};
           /set_to_FALSE/ && seen[$3$2] { delete seen[$3$2] }' logfile.txt

関連情報