私のサーバーには巨大なログファイル(数十GB)があります。適切な時間にダウンロードするには容量が大きすぎます。しかし、私は比較的小さな線のサブセットにのみ興味があります。ログファイルはXMLと同様の構造を持っています。多くの項目があり、<log>...</log>
そのうちの1つに私が探している特定のパターンがあります。たとえば"Failure"
(一致項目が1つしかない場合grep
)"Failure"
:
<log>...</log>
<log>...</log>
....
<log> (*1*)
...
... "Failure" ...
...
</log> (*2*)
....
<log>...</log>
<log>...</log>
私の考えは、前と次の項目と含まれている行の前と後の場所を別々に検索することです<log>
(*1*)
。後でこの行を別のファイルにコピーして簡単にダウンロードできるようにしたいと思います。</log>
(*2*)
"Failure"
擬似コードの概要:
failure_line = find pattern "Failure" in log file
start_line = find immediate previous occurrence of <log> before the line failure_line
finish_line = find immediate next occurrence of </log> after the line failure_line
copy all lines from start_line until finish_line to a new file
bash
多くのオーバーヘッドなしでスクリプトを介してこれを達成できますか?
ベストアンサー1
sed
perl
などの標準テキスト処理ツールは、XMLawk
の解析には使用されません。<log>...</log>
連続して複数のペアを持たないなどの方法を使用できる場合は、次のことができますsed
。
sed '/<log>.*<\/log>/{/Failure/p;d;};/<log>/,/<\/log>/H;/<log>/h;/<\/log>/!d;x;/Failure/!d' your.log
- '/.*</log>/' は完全なタグ付き行と一致します。これらの項目は個別に処理する必要があります。
/Failure/p
含まれている場合は印刷し、Failure
追加d
処理を停止します。 - 次に、開始と終了の間の行を
/<log>/,/<\/log>/
選択し、予約済みスペースのクリップボードに追加します()。<log>
</log>
sed
H
/<log>/h
log
新しいシーケンス用に予約されたスペースを初期化します。/<\/log>/!d
閉じる行を除くすべての行の処理を停止します。</log>
- したがって、ログを閉じるときは、次のようにします。
x
保留スペースとパターンスペースを交換すると、前の行以降のパターンスペース内のすべての項目が収集されます<log>
。d
含まれていない場合は削除してくださいFailure
。それ以外の場合、デフォルトではスクリプトの最後に印刷されます。