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
各セッションに対応するtype
and isまたはset_to
がTRUE
ある場合は、andスコープをFALSE
使用してsed
以下を実行できます。
sed '/type=m/,/set_to_/!d;/set_to_TRUE$/!d;s/.*\(sessionid-.*\);.*/\1/' infile
/type=m/,/set_to_/
範囲に含まれていないすべての行が削除されます。また、範囲がで終わらない行を削除しますset_to_TRUE
。sessionid
次に、残りの行(存在する場合)から抽出します。
または、
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_TRUE
set_to_FALSE
注:上記のスクリプトは一致するセッションIDのみを印刷します。実際のtype=m
合計行を印刷するには、set_to_TRUE
awkスクリプトは次のようになります。
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