awkを使用してファイルから非常に特定の部分を抽出する

awkを使用してファイルから非常に特定の部分を抽出する

私は人々が私を電話会議にドラッグしたり、ファイル全体を収集するのではなく、簡単に送信できるように、デバッグログの重要な部分を抽出するスクリプト(実際には1行スクリプト)を作成したいと思います。情報を得るためにlessやviで何をすべきかを教えてもらえますが、可能であればコマンドとして使用したいと思います。

存在するless

$ less filename
G
?Server\ version
/SEVERE
[read line including first match for SEVERE from this point, stop reading when get to next instance of SEVERE]

これを行うためにコマンドを作成しようとしましたが、うまくいきませんawkでした。

これは私が得た最も近い結果ですが、うまくいきません。

awk '{if (/Server version/) {chunk=""} else {chunk=chunk $0 RS}} END {printf "%s", chunk}'  filename | awk '/SEVERE/,/SEVERE/'

awk最後に印刷したい部分の始めと終わりに同じパターンを使用するのが好きではないようです。

他のツールを使用する意向がありますが、ユースケースでは、RHEL7でデフォルトで提供されているユーティリティを使用する必要があります。

この情報が役立つ場合は、Apache Tomcatのデバッグログを見てみましょう。

答え1

SEVERE私が正しく理解した場合は、最初の発生と最後の発生から次の発生の間の行を出力したいと思いますServer version

入力ファイルの例:

Server version
SEVERE
ignore
SEVERE
Server version
ignore
SEVERE
important
stuff
SEVERE 
ignore
SEVERE
awk '
  /Server version/{ chunk="" }
  /SEVERE/{ logme=(chunk=="") }
  logme{ chunk=chunk $0 RS }
  END{ printf "%s", chunk }
' file

出力:

SEVERE
important
stuff

答え2

複数行の概要:grepを使用して行番号を印刷して抽出し、awkを使用します。

grep -n SEVERE filename | head -n 2 | cut -d ':' -f1

これにより、「SEVERE」を含む最初の2つの行番号[a、b]が出力され、awkはSEVEREと中間行を簡単に印刷できます。

awk 'NR>=a && NR<=b {print $0;}' filename

これは簡単にスクリプトで書くことができますが、ログファイルを2回渡す必要があります。

関連情報