如何查找模式最后一次出现位置并打印其前20行
解决方案:获取模式最后一次出现位置的前20行及模式本身
最优单Awk命令(兼容所有POSIX环境)
直接用一条Awk命令就能完成需求,无需多进程调用,效率更高且兼容性拉满:
awk '/====/ {pos=NR} END {start=(pos<20?1:pos-20); for(i=start;i<=pos;i++) print lines[i]} {lines[NR]=$0}' inputfile
命令逻辑说明:
- 遍历文件时,每匹配到
====模式,就更新pos变量为当前行号(最终pos就是模式最后一次出现的行号) - 同时把每一行内容存入数组
lines,用行号NR作为索引 - 到文件结尾的
END块时:- 计算起始行号
start:如果最后匹配行的行号小于20,就从第1行开始;否则从pos-20开始 - 循环打印从
start到pos的所有行,包含模式行本身,且不会打印模式后的内容
- 计算起始行号
对比原有脚本的优势
你原来的分步骤脚本虽然能运行,但存在以下问题:
- 需要启动
awk+expr+awk三个进程,处理大文件(比如2万行)时效率更低 - 没有处理
holdline<20的边界情况(此时befholdline会是负数,虽Awk会自动忽略负数的NR判断,但逻辑不够严谨) - 代码冗余,不如单条Awk命令简洁
补充:改进版Sed方案(仅作参考)
如果一定要用Sed,也可以实现,但逻辑相对复杂,且依赖Sed的保持空间操作,不如Awk直观:
sed -n ' /====/ { # 匹配到模式时,清空保持空间,存入当前行及之前19行 H s/\n//g h n b } # 非模式行,将当前行追加到保持空间,然后只保留最后20行 H s/.*\(\n.*\)\{20\}/\1/ h $ { # 最后一行时,取出保持空间并打印 x p } ' inputfile
不过这个Sed方案对换行符的处理需要注意,且部分极简版Sed可能不支持大括号语法,还是推荐Awk方案。
内容的提问来源于stack exchange,提问作者Aires69
相关产品推荐
相关产品推荐

