ログファイルから1行のパターンをgrepし、次のパターンが表示されるまで次のn行を印刷します。

ログファイルから1行のパターンをgrepし、次のパターンが表示されるまで次のn行を印刷します。

log.txt ファイルに次の内容が含まれているとします。

[12] 03/31/21 08:33:30.080851 T(12581) _DBG message x 1
[12] 03/31/21 08:33:30.080851 T(34897) _DBG message y 1
[12] 03/31/21 08:33:31.241167 T(12344) _DBG message z 1
[12] 03/31/21 08:33:31.457612 T(34897) _DBG message y 2
                        test message line 2
                        test message line 3 
                        test message line 4 
[12] 03/31/21 08:33:31.78912 T(12344) _DBG message z 2
[12] 03/31/21 08:33:32.56341 T(34897) _DBG message y 3
[12] 03/31/21 08:33:33.12789 T(12581) _DBG message x 2
                        test message for x
[12] 03/31/21 08:33:33.78123 T(34897) _DBG message y 3
                        test message line 2
[12] 03/31/21 08:33:34.12342 T(12581) _DBG message x 3
[12] 03/31/21 08:33:34.56712 T(34897) _DBG message y 4

必要な出力は次のようになります。

[12] 03/31/21 08:33:30.080851 T(34897) _DBG message y 1
[12] 03/31/21 08:33:31.457612 T(34897) _DBG message y 2
                        test message line 2
                        test message line 3 
                        test message line 4 
[12] 03/31/21 08:33:32.56341 T(34897) _DBG message y 3
[12] 03/31/21 08:33:33.78123 T(34897) _DBG message y 3
                        test message line 2
[12] 03/31/21 08:33:34.56712 T(34897) _DBG message y 4

スレッドIDが与えられたら、そのメッセージに属する行+次の数行を印刷する必要があります。目的の出力では、他のすべてのスレッドメッセージが削除されます。

以下でsedコマンドを試しましたが、次の行も印刷します(他のスレッドメッセージです)。

sed -n -e '/T(34897)/,/_DBG/ p' log.txt 

別のgrep/awk/regexコマンドを試しましたが、これを行うことはできません。助けてください

答え1

$ awk -v t=34897 '/^\[/{f=($4=="T("t")")} f' file
[12] 03/31/21 08:33:30.080851 T(34897) _DBG message y 1
[12] 03/31/21 08:33:31.457612 T(34897) _DBG message y 2
                        test message line 2
                        test message line 3
                        test message line 4
[12] 03/31/21 08:33:32.56341 T(34897) _DBG message y 3
[12] 03/31/21 08:33:33.78123 T(34897) _DBG message y 3
                        test message line 2
[12] 03/31/21 08:33:34.56712 T(34897) _DBG message y 4

fで始まる行を見るたびに、その行に「found」フラグが設定されます[。行の4番目のフィールドT(<target value>)がtrue(1)に設定されると、ffalse(0)に設定されます。各行を読み取るときにftrueの場合、現在の行が印刷されます。

他のawkスクリプトと同様に、他の形式で見てデフォルトに依存しないので、簡単で明確にしたい場合は、GNU awkを使用して見やすく印刷できます(注:他の形式ではなくgawkである必要があります)。 awkバリアント)は次のとおりですawk -o- ...

$ awk -o- -v t=34897 '/^\[/{f=($4=="T("t")")} f' file
/^\[/ {
        f = ($4 == "T(" t ")")
}

f {
        print
}

答え2

このawkスクリプトを使用してください。

BEGIN {
  doprint = 0
  marker = "T("thread")"
}

$1 ~ /\[[0-9]+\]/ {
   if( $4 == marker ) {
      doprint = 1
   } else {
      doprint = 0
   }
}

doprint==1 { print }

次のように呼び出されます。

$ awk -v thread="34897" -f 642963.awk input.txt
[12] 03/31/21 08:33:30.080851 T(34897) _DBG message y 1
[12] 03/31/21 08:33:31.457612 T(34897) _DBG message y 2
                        test message line 2
                        test message line 3
                        test message line 4
[12] 03/31/21 08:33:32.56341 T(34897) _DBG message y 3
[12] 03/31/21 08:33:33.78123 T(34897) _DBG message y 3
                        test message line 2
[12] 03/31/21 08:33:34.56712 T(34897) _DBG message y 4

答え3

まず、フィールドベースの正規表現を定式化するのに役立ついくつかの補助変数を定義します。

# definition of a unit space
_s_='[:space:]'

# regex for a space char and nonspace char
s="[$_s_]" S="[^$_s_]"

# a field is a run of nonspaces followed by a run of spaces
F="$S\{1,\}$s\{1,\}"

   id=34897

sed -ne ":top
  /^\[$S*$s$s*\($F\)\{2\}T($id)$s/{
    :nxt
      p;n
    /^$s/b nxt
    b top
  }
" file

関連情報