两个标签之间的多行grep,只显示最后一个匹配

两个标签之间的多行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

你可以像这样通过管道传输两个 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

相关内容