2つのタグ間の複数行のgrepで最後の一致のみを表示する

2つのタグ間の複数行のgrepで最後の一致のみを表示する

データセグメントをログ出力に混在させるプログラムがあります。

log message
log message
----BEGIN INLINE DATA----
data
data
data
-----END INLINE DATA-----
log messge

似たようなものを探していますが、

awk '/-BEGIN INLINE DATA-/,/-END INLINE DATA-/'

ただし、周囲の「ラベル」ではなく最後のデータセグメントのみを印刷する必要があります。

答え1

awk を使用して開始マーカーの後にデータの蓄積を開始し、終了マーカーに出会うと停止します。新しいスタートマーカーが表示されたら、データアキュムレータを再初期化します。

awk '
    /-BEGIN INLINE DATA-/ {data = ""; storing = 1}
    /-END INLINE DATA-/ {storing = 0}
    storing {data = data "\n" $0}
    END {print data}
'

答え2

次のように2つのsedをパイプできます。

<your program> | tac | sed '1,/END INLINE DATA/d' | sed '/BEGIN INLINE DATA/,$d' | tac

答え3

tac log.txt | sed '1,/END INLINE DATA/d' | sed '/BEGIN INLINE DATA/,$d' | tac

仕事を終えると思います。

答え4

Perlでこれを行ういくつかの珍しい方法は次のとおりです。

perl -ne '
  BEGIN{ $/="----BEGIN INLINE DATA----\n" } # Set input record separator

  $payload= s/----END INLINE DATA----.*\z//rs; # Remove end marker and messages

  END{ print $payload } # Print the last payload

' file

これにはPerl v5.14以降が必要です。以前のバージョンのPerlを使用する場合は、追加の行が必要です。

perl -ne '
  BEGIN{ $/="----BEGIN INLINE DATA----\n" } # Set input record separator

  $payload= $_; # Copy current line into $payload
  $payload=~ s/----END INLINE DATA----.*\z//s; # Remove end marker and messages

  END{ print $payload } # Print the last payload

' file

関連情報