如何用sed结合正则AND/OR条件删除test1上方的指定行?
嘿,我来帮你搞定这个sed的难题!你需要删除test1上方的行,条件是那行要么不含test1,要么不以引号结尾——这个需求核心是要处理行上下文(关联当前行和它的前一行),sed的保持空间(hold space)正好能帮我们做到这一点。
需求拆解
先明确逻辑:对于每一行包含test1的行,我们要检查它的前一行:
- 如果前一行「不包含
test1」或者「不以引号结尾」→ 删除前一行,只保留test1所在行 - 如果前一行「既包含
test1又以引号结尾」→ 同时保留前一行和test1所在行
解决方案:用sed保持空间处理上下文
这里有两个版本,一个是逻辑清晰的分步版,一个是简化版,你可以按需选择:
版本1:逻辑清晰的分步实现
sed -n ' # 第一行直接存入保持空间,无前置行可处理 1h # 从第二行开始处理每一行 1!{ # 将当前行追加到保持空间,此时保持空间是「前一行\n当前行」 H # 交换保持空间和模式空间,现在模式空间里存着两行内容 x # 检查当前行(模式空间第二行)是否包含test1 /test1/{ # 先判断前一行是否不含test1 /^\(.*test1.*\)$/!{ # 去掉前一行,只输出当前行 s/.*\n//p b } # 前一行包含test1,再判断是否以引号结尾 /"$/{ # 两行都符合保留条件,输出整段 p b } # 前一行包含test1但不以引号结尾,只输出当前行 s/.*\n//p b } # 当前行不含test1,输出前一行,再把当前行存入保持空间 s/\n.*//p s/.*\n//h } # 处理最后一行:如果最后一行不含test1,输出它 ${/test1/!p} ' your_file.txt
版本2:用正则OR条件简化
我们可以把「不包含test1 或者 不以引号结尾」转化为「不满足(包含test1 且 以引号结尾)」,用一个正则就能搞定,命令更简洁:
sed -n ' 1h 1!{ H;x # 当当前行包含test1时 /test1/{ # 如果前一行不满足「包含test1且以"结尾」,就去掉前一行 /^\(.*test1.*"$\)/!s/.*\n// # 输出处理后的内容 p }!{ # 当前行不含test1,输出前一行并更新保持空间 s/\n.*//p s/.*\n//h } } ${/test1/!p} ' your_file.txt
关键细节说明
-n:让sed默认不输出任何行,我们手动控制哪些行需要输出,避免多余内容- 保持空间(
h/H/x命令):用来暂存前一行的内容,实现行与行之间的关联处理 - 正则部分:如果你的引号是单引号,只需要把命令里的
"换成'即可(注意sed中单引号的转义,GNU sed可以用\',或者用'\''来嵌套)
测试示例
假设你的输入文本是:
line1 no test1, ends with " line2 has test1, ends with " test1 line3 line4 no test1, no quote test1 line5 line6 has test1, no quote test1 line7
运行命令后会得到:
line2 has test1, ends with " test1 line3 test1 line5 test1 line7
完全符合你的需求:删除了不符合条件的前置行,保留了符合条件的内容。
内容的提问来源于stack exchange,提问作者Jojoleo
相关产品推荐
相关产品推荐

