如何用sed/awk/grep删除含'-- END OF ENTRY --'的行及其前两行?
解决方案:删除指定结尾行及其前两行
用 sed 实现
sed可以通过维护一个行缓冲区跟踪最近两行,遇到目标行时直接跳过这三行(当前行+前两行),命令如下:
sed -n '1{N;N};/-- END OF ENTRY --/{s/.*//;x;d};p;x' filename
说明:
1{N;N}:读取第一行时,额外再读入接下来两行,初始化缓冲区内容/-- END OF ENTRY --/:匹配到目标行时,清空当前内容并交换缓冲区后直接跳过,相当于丢弃这三行p;x:没匹配到目标行时,输出当前行,然后交换模式空间和缓冲区,确保缓冲区始终保存最近两行
要直接修改原文件(原地编辑),加上-i参数即可:
sed -i '1{N;N};/-- END OF ENTRY --/{s/.*//;x;d};p;x' filename
用 awk 实现
awk通过两个变量记录前两行内容,遇到目标行时不输出这三行,否则正常输出并更新记录:
awk 'prev2 != "" {print prev2} /-- END OF ENTRY --/ {prev1="";prev2="";next} {prev2=prev1;prev1=$0} END {if(prev1!="")print prev1;if(prev2!="")print prev2}' filename
说明:
- 用
prev1存上一行内容,prev2存上上行内容 - 每次先输出
prev2(如果有内容),再检查当前行是不是目标行:是的话清空变量并跳过;不是的话更新变量,把prev1的值传给prev2,当前行赋值给prev1 - 最后在END块输出剩下的未处理行,避免末尾两行被遗漏
awk没有原生原地编辑功能,需要借助临时文件:
awk 'prev2 != "" {print prev2} /-- END OF ENTRY --/ {prev1="";prev2="";next} {prev2=prev1;prev1=$0} END {if(prev1!="")print prev1;if(prev2!="")print prev2}' filename > temp && mv temp filename
批量处理多个文件
如果要处理目录下所有.txt文件,用循环即可:
sed 批量处理
for file in *.txt; do sed -i '1{N;N};/-- END OF ENTRY --/{s/.*//;x;d};p;x' "$file" done
awk 批量处理
for file in *.txt; do awk 'prev2 != "" {print prev2} /-- END OF ENTRY --/ {prev1="";prev2="";next} {prev2=prev1;prev1=$0} END {if(prev1!="")print prev1;if(prev2!="")print prev2}' "$file" > temp && mv temp "$file" done
内容的提问来源于stack exchange,提问作者SquarePeg
相关产品推荐
相关产品推荐

