从底部提取行直到正则表达式匹配

Sat*_*ish 5 linux command-line sed awk regular-expression

我有这个输出。

[root@linux ~]# cat /tmp/file.txt
virt-top time  11:25:14 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.0  0.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.0  0.0  95:44:07 instance-00000372
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372
Run Code Online (Sandbox Code Playgroud)

你可以看到它有两个块,我想提取最后一个块(如果你看到第一个块,它的 CPU 全部为零,我不在乎)总之我想提取最后几行(注意:有时我有两个以上的实例-*) 否则我可以使用“tail -n 2”

1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372
Run Code Online (Sandbox Code Playgroud)

我已经尝试了 sed/awk/grep 和所有可能的方法,但没有接近想要的结果。

ilk*_*chu 9

这感觉有点傻,但是:

$ tac file.txt |sed -e '/^virt-top/q' |tac
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372
Run Code Online (Sandbox Code Playgroud)

GNUtac反转文件(许多非 GNU 系统都有tail -r),sed选择行直到第一个以virt-top. 您可以添加sed 1,2dtail -n +3删除标题。

或者在 awk 中:

$ awk '/^virt-top/ { a = "" } { a = a $0 ORS } END {printf "%s", a}' file.txt 
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372
Run Code Online (Sandbox Code Playgroud)

它只是将所有行收集到一个变量中,并清除以virt-top.

如果文件非常大,tac+sed解决方案肯定会更快,因为它只需要读取文件的尾端,而awk解决方案从顶部读取整个文件。