首页 > 解决方案 > 如何使用 sed 仅打印文件中紧接在空行之前的行?

问题描述

我有一个具有以下结构的文本文件:

bla1
bla2

bla3
bla4

bla5

所以你可以看到一些文本行前面有一个空行。

我知道 sed 有两个缓冲区的概念,一个模式空间缓冲区和一个保持空间缓冲区,所以我猜这些需要在这里发挥作用,但我不清楚如何指定它们来完成我需要的。

在我上面的人为示例中,我希望看到输出以下行:

bla3
bla5

标签: awksed

解决方案


sed 用于在单独的行上执行 s/old/new,仅此而已。任何时候你开始谈论缓冲区或做任何与多行比较相关的事情,你都在使用错误的工具。

你可以用 awk 做到这一点:

$ awk -v RS= -F'\n' 'NR>1{print $1}' file
bla3
bla5

但是如果文件中的第一行是空的,它将无法打印第一个非空行,因此如果您希望所有空格字符的行都被视为空行,这可能就是您想要的:

$ awk 'NF && !p{print} {p=NF}' file
bla3
bla5

否则:

$ awk '($0!="") && (p==""){print} {p=$0}' file
bla3
bla5

即使在任何给定的非空行之前有多个空行,上述所有内容都将起作用。

要查看这 3 种方法之间的区别(鉴于问题中的示例输入,您不会看到):

PS1> printf '\nfoo\n      \nbar\n\netc\n' | cat -E
$
foo$
      $
bar$
$
etc$

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk -v RS= -F'\n' 'NR>1{print $1}'
etc

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk 'NF && !p{print} {p=NF}'
foo
bar
etc

PS1> printf '\nfoo\n      \nbar\n\netc\n' | awk '($0!="") && (p==""){print} {p=$0}'
foo
etc

推荐阅读