我有这个输出。
[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
你可以看到它有两个块,我想提取最后一个块(如果你看到第一个块,它的 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
我已经尝试了 sed/awk/grep 和所有可能的方法,但没有接近期望的结果。
这感觉有点傻,但是:
GNU
tac
反转文件(许多非 GNU 系统有tail -r
),sed
选择行直到第一个以virt-top
. 您可以添加sed 1,2d
或tail -n +3
删除标题。或者在 awk 中:
它只是将所有行收集到一个变量中,并在以
virt-top
.如果文件很大,
tac
+sed
解决方案肯定会更快,因为它只需要读取文件的尾部,而awk
解决方案从顶部读取整个文件。ed
您可以使用正则表达式向上搜索代替通常的?pattern?
(/pattern/
从当前位置上方搜索)。例如:如果您的输入具有固定数量的块,您还可以执行以下操作:
输出从第 2 次出现的行到文件
virt-top
末尾的行(0 表示false,表示第一个结束,最后一个范围永远找不到)。从以字符串开头的行
virt-top
到结尾的最后一条记录使用ed
(适用于处理大小与您显示的文件相当的文件,而不是几兆字节大):virt-top
或者,仅包含子字符串的最后一行之后的行instance
:最后一个
ed
命令 ,?^virt-top?,$g/instance/p
首先指定从最后一行以virt-top
(last, 因为ed
从缓冲区的最后一行开始并向?re?
后搜索) 到缓冲区末尾 ($
) 的行范围,并将命令g/instance/p
应用于这些线。该g/re/p
命令打印范围内与给定正则表达式匹配的所有行(grep
顺便说一下,这就是它的名称)。使用
awk
:lines
只要有一行包含 substring ,这就会保存输入行instance
。这些行打印在最后。每当找到以 开头的行时,virt-top
将丢弃已保存的行。与 几乎相同
sed
,使用保持空间作为代码中lines
变量的等效项awk
:这是另一种处理它的方法:
结果