我有一个具有以下结构的文本文件:
bla1
bla2
bla3
bla4
bla5
因此您可以看到某些文本行之前有一个空行。
我知道sed具有两个缓冲区的概念,即模式空间缓冲区和保持空间缓冲区,因此我猜想它们需要在这里发挥作用,但是我不清楚如何指定它们以完成操作我需要。
在上面人为设计的示例中,我希望看到输出以下行:
bla3
bla5
答案 0 :(得分:2)
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
即使在任何给定的非空行之前有多个空行,上述所有内容都将起作用。
要查看这三种方法之间的区别(鉴于问题中的示例输入,您将看不到):
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
答案 1 :(得分:1)
您可以使用保留缓冲区轻松地在空白之前打印行,如下所示:
sed -n -e '/^$/{x; p;}' -e h input
但是,我看不出将其用于您的用例的简单方法。对于您的情况,可以使用:
sed -n -e '/^$/ba' -e d -e :a -e n -e p input
但是我会用awk
来做到这一点。
awk 'NR!=1{print $1}' RS= FS=\\n input-file
答案 2 :(得分:1)
awk 'p;{p=/^$/}' file
以上命令对每一行执行以下操作:
p
是1
,则打印行; p
设置为1
。如果由一个或多个空格组成的行也被认为是空的:
awk 'p;{p=!NF}' file
要打印每个非空行紧跟在空行之后,您可以使用以下方法:
awk 'p*!(p=/^$/)' file
p
为1
并且此行不为空(1*!(0) = 1*1 = 1
),则打印此行; 1*!(1) = 1*0 = 0
,0*anything = 0
),什么也不打印。请注意,此代码可能不适用于所有awks,它的可移植版本如下:
awk 'p*(/./);{p=/^$/}' file
如果由一个或多个空格组成的行也被认为是空的:
awk 'p*NF;{p=!NF}' file
答案 3 :(得分:0)
如果sed / awk不是必需的,则可以使用grep来实现:
grep -A 1 '^$' input.txt | grep -v -E '^$|--'
答案 4 :(得分:0)
您可以使用sed
来匹配一系列行,并在匹配项内进行子匹配,如下所示:
# - use the "-n" option to omit printing of lines
# - match lines between a blank line (/^$/) and a non-blank one (/^./),
# then print only the line that contains at least a character,
# i.e, the non-blank line.
sed -ne '
/^$/,/^./ {
/^./{ p; }
}' input.txt
答案 5 :(得分:0)
经gnu sed测试,您的数据在“ a”中:
$ sed -nE '/^$/{N;s/\n(.+)/\1/p}' a
bla3
bla5
在实际编辑中,-i选项在-n之前