我有一个看起来像这样的文件:
Guest-List 1
All present
Guest-list 2
All present
Guest-List 3
Guest-list 4
All present
Guest-list 5
我想删除包含“All present”及其标题的行(“All present”上方的行)。所需的输出是:
Guest-List 3
Guest-list 5
我有兴趣使用sed实现这一点。因为我是菜鸟,所以没有sed的其他可能的解决方案也会受到赞赏(回答时请提供详细解释,以便我可以学习):)
(我知道可以删除匹配正则表达式的行,并且可以存储它上面的行,将它发送到保持缓冲区,如下所示:sed'/^.*present$/d; h'...然后“g”命令会将保持缓冲区复制回模式空间......但是如何告诉sed删除它呢?)
提前致谢!
答案 0 :(得分:3)
您可以像这样使用fgrep
:
fgrep -v -f <(fgrep 'All present' -B1 file) file
Guest-List 3
Guest-list 5
答案 1 :(得分:2)
sed -n '/All present$/{s/.*//;x;d;};x;p;${x;p;}' file | sed '/^$/d'
file
是您的档案。
这是here.
的改编示例它有一个很好的解释:
为了删除模式之前的行,我们将每一行存储在一个称为保持空间的缓冲区中。每当模式匹配时,我们删除两者中存在的内容,包含当前行的模式空间,包含前一行的保留空间。
让我解释一下这个命令:
x;p;
;这将针对每一行执行。x
用保留空间交换模式空间的内容。p
打印模式空间。结果,每次当前行都占据空间,前一行进入模式空间并被打印。当模式/All Present/
匹配时,我们清空(s/.*//
)模式空间,并用保留空间交换(x
)(因此保持空间变空)并删除(d
)包含前一行的模式空间。因此,当遇到Linux模式时,当前行和前一行被删除。${x;p;}
将打印最后一行,如果离开,它将保留在保留空间中。
sed
的第二部分是删除第一个sed
命令创建的空行。
答案 2 :(得分:0)
如果你在sed中使用的命令多于s,g和p(带-n)命令,那么你使用的语言结构在20世纪70年代中期发明时已经过时了。
sed是一个很好的工具,可以在一行上进行简单的替换,其他任何东西只需使用awk:
$ cat file
Guest-List 1
All present
Guest-list 2
All present
Guest-List 3
Guest-list 4
All present
Guest-list 5
$ awk 'NR==FNR{ if (/All present/) {skip[FNR-1]; skip[FNR]} next} !(FNR in skip)' file file
Guest-List 3
Guest-list 5
以上只是解析文件两次 - 第一次创建一个名为skip
的行号(FNR
)数组,你不想输出,第二次打印行是不在那个数组中。简单,清晰,可维护,可扩展,......