我用这个
cat foo.txt | sed '/bar/d'
删除bar
文件中包含该字符串的行。
不过我想删除这些行以及紧随其后的一行。最好在sed
或awk
MinGW32 中可用的其他工具中。
这是一种grep
与我可以打印匹配行-A
以及-B
匹配行之前/之后的行相反的操作。
有什么简单的方法可以实现吗?
答案1
如果您有 GNU sed(非嵌入式 Linux 或 Cygwin):
sed '/bar/,+1 d'
如果有bar
两行连续,这将删除第二行而不对其进行分析。例如,如果您有一个 3 行文件bar
// bar
,foo
则该foo
行将保留。
答案2
如果bar
可能出现在连续行上,您可以这样做:
awk '/bar/{n=2}; n {n--; next}; 1' < infile > outfile
通过将上面的 2 更改为要删除的行数(包括匹配的行),可以适用于删除 2 行以上。
如果没有,很容易sed
完成@MichaelRollins 的解决方案或者:
sed '/bar/,/^/d' < infile > outfile
答案3
我对 sed 不太熟悉,但在 awk 中很容易做到这一点:
awk '/bar/{getline;next} 1' foo.txt
awk 脚本的内容是:对于包含 bar 的行,获取下一行(getline),然后跳过所有后续处理(next)。末尾的 1 模式打印剩余的行。
更新
正如评论中指出的,上述解决方案不适用于连续的bar
.这是考虑到这一点的修订后的解决方案:
awk '/bar/ {while (/bar/ && getline>0) ; next} 1' foo.txt
我们现在继续阅读以跳过所有 /bar/ 行。
答案4
如果应删除紧随匹配项之后的任何行,那么您的sed
程序将不得不考虑连续的匹配项。换句话说,如果您删除了匹配项后面的一行,并且该行也匹配,那么您可能也应该删除该行后面的行。
它的实现非常简单——但你必须稍微回顾一下。
printf %s\\n 0 match 2 match match \
5 6 match match match \
10 11 12 match 14 15 |
sed -ne'x;/match/!{g;//!p;}'
0
6
11
12
15
它的工作原理是交换读入的每一行的保持空间和模式空间 - 因此每次都可以将最后一行与当前行进行比较。因此,当sed
读取一行时,它会交换其缓冲区的内容 - 前一行是其编辑缓冲区的内容,而当前行则放入保留空间。
因此sed
检查前一行是否有匹配项match
,如果未找到,则运行函数!
中的两个表达式。将通过覆盖模式空间来设置保留空间 - 这意味着当前行同时位于保留空间和模式空间中 - 然后它将检查它是否与其最近编译的正则表达式匹配 -{
}
sed
g
//
match
- 而如果它才不是match
它被p
印刷了。
这意味着只有在不存在的情况下才会打印一行match
和紧接的前一行没有match
。它还放弃了对序列的任何不必要的交换match
es.
如果您想要一个可以删除在match
它需要更多的工作:
printf %s\\n 1 2 3 4 match \
match match 8 \
9 10 11 12 13 \
14 match match \
17 18 19 20 21 |
sed -net -e'/match/{h;n;//h;//!H;G;s/\n/&/5;D;}' -ep
...将 5 替换为行数(包括匹配行)您想要删除的...
1
2
3
4
12
13
14
21