删除包含特定字符串的行和以下行

删除包含特定字符串的行和以下行

我用这个

cat foo.txt | sed '/bar/d'

删除bar文件中包含该字符串的行。

不过我想删除这些行以及紧随其后的一行。最好在sedawkMinGW32 中可用的其他工具中。

这是一种grep与我可以打印匹配行-A以及-B匹配行之前/之后的行相反的操作。

有什么简单的方法可以实现吗?

答案1

如果您有 GNU sed(非嵌入式 Linux 或 Cygwin):

sed '/bar/,+1 d'

如果有bar两行连续,这将删除第二行而不对其进行分析。例如,如果您有一个 3 行文件bar// barfoo则该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,如果未找到,则运行函数!中的两个表达式。将通过覆盖模式空间来设置保留空间 - 这意味着当前行同时位于保留空间和模式空间中 - 然后它将检查它是否与其最近编译的正则表达式匹配 -{}sedg//match- 而如果才不是match它被p印刷了。

这意味着只有在不存在的情况下才会打印一行match 紧接的前一行没有match。它还放弃了对序列的任何不必要的交换matches.

如果您想要一个可以删除在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

相关内容