如何让sed打印一系列行,直到它看到两个连续的空白行?

如何让sed打印一系列行,直到它看到两个连续的空白行?,sed,Sed,我想使用这样的sed脚本 #n /^TODO/,/^$/p 除了sed应该在遇到两个连续的空行(而不是一个空行)后停止打印范围之外。然后它应该继续扫描下一个感兴趣的范围。换句话说,兴趣范围的末尾由两个空行定义。我甚至不确定地址范围是否能满足这种要求,因此如果有其他方法,请告诉我。使用sed进行简单替换 $ more file 1 2 blah blah TODO blah blah 4 5 6 7 8 9 10 11 end $ awk -vRS="\n\n" '/TODO/{prin

我想使用这样的sed脚本

#n
/^TODO/,/^$/p

除了sed应该在遇到两个连续的空行(而不是一个空行)后停止打印范围之外。然后它应该继续扫描下一个感兴趣的范围。换句话说,兴趣范围的末尾由两个空行定义。我甚至不确定地址范围是否能满足这种要求,因此如果有其他方法,请告诉我。

使用sed进行简单替换

$ more file
1
2
blah blah
TODO
blah blah
4
5


6
7
8
9
10


11
end
$ awk -vRS="\n\n" '/TODO/{print;exit}' file
1
2
blah blah
TODO
blah blah
4
5
概念证明 $cat double_blank.txt 福 酒吧 巴兹 废话 一 二 三 结果 $sed'N/^\n$/q;PD'double_blank.txt 福 酒吧 巴兹

当遇到非空行的空行奇数/偶数配对时,应停止两条连续的空行:

sed -n 'N;/^\n$/q;P;D'
不要打印这两个空行:

sed -n 'N;/^\n$/q;P;D'
打印其中一个:

sed -n 'N;/^\n$/{P;q};P;D'
打印这两个文件:

sed -n 'N;/^\n$/{p;q};P;D'
编辑:

以下是您如何在自己的范围内实现这一目标:

sed -n '/^TODO/,${N;/^\n$/q;P;D}'
编辑2:

根据dan的评论和编辑要求,这似乎可以在一个文件中多次以两行空白结束的范围内找到模式:

sed -n '/^TODO/,/^$/{H;N;/^\n$/{b};p}'

基于SiegeX的答案:

cat > lines <<'EOF'
a


c
d
EOF
sed '/^$/N; /^\n$/q' lines
cat>lines这可能适合您:

sed -n '/TODO/{:a;N;/\n\n$/s///p;Ta}' file
这将严格遵守OP问题,如果每个范围包含两个连续的换行符,则仅打印范围减去两个换行符

如果文件结束也表示该范围结束,则使用:

sed -n '/TODO/{:a;p;n;/^$/!ba;n;//b;x;p;x;ba}' file
注意:当一个空行后面没有另一个空行时,使用保留空间来提供一个空行


此外,第一个解决方案可以打印两个换行:

sed -n '/TODO/{:a;N;/\n\n$/!ba;p}' file
或者换行:

sed -n '/TODO/{:a;N;/\n\n$/s//\n/p;Ta}' file
不要使用地址范围 相反,寻找TODO块的开头,然后循环直到找到这对空行

这是一个测试文件。之后是对一些建议解决方案的比较

cat >tricky_todo.txt <<EOF
TODO block 1 line 1 (last line)


THIS LINE SHOULDN'T BE PRINTED #1
THIS LINE SHOULDN'T BE PRINTED #2
TODO block 2 line 1
     block 2 line 2
     block 2 line 3
     block 2 line 4

     block 2 line 6
     block 2 line 7
     block 2 line 8 (last line)


TODO block 3 line 1
     block 3 line 2
     block 3 line 3
     block 3 line 4
     block 3 line 5 (last line)


TODO block 4 line 1
     block 4 line 2
     block 4 line 3
     block 4 line 4
     block 4 line 5 (last line)


THIS LINE SHOULDN'T BE PRINTED #3
THIS LINE SHOULDN'T BE PRINTED #4
EOF
我的脚本的输出 注意事项:如果TODO块是文件中的最后一个内容,则它必须按照OP中的规定在两个空行中结束,否则将被删除



sed-n'/^TODO/{:a;n;s/\n\n$/;Ta;p}
sed
是一个流编辑器。对于基于行内容的文本处理,最好使用其他工具,如awk或perlThanks。我会调查的。但我认为一些涉及H,N,N等的高级sed可能仍然会起作用。是的,sed是可能的。请看我的答案。另外,我注意到你还没有接受你提出的四个问题的任何答案。这样做是一种很好的礼节,因为它有利于其他可能有类似问题的人。此外,我想你会发现,如果你这样做,人们会更愿意为你提供更深入的答案。谢谢你的建议。我是这个网站的新手,只是想弄清楚事情是如何运作的。在公认的答案中,“编辑2”有三种方式失败:1)如果TODO块是奇数行,则将打印一对空行后面的行;2) 如果案例1中的额外行恰好是另一个TODO块的开始,则不会打印该块的其余部分;3)如果在块中的奇数行上有一条空白行(计数为1),后面是非空行,则在该块中有更多行,空行将满足地址范围的末尾,因此在非空行之后,块的打印将被截断。没有遇到第二个空行。另外,您的第一个文件在打印第一个文件时(在“4”之前)会添加一个空行。在
awk
中使用
RS
是一个好主意。您只需要另一个
\n
RS=“\n\n\n”
)。如果行与“非空白/空白”和“空白/非空白”成对,则此操作将失败。如果第二对为“blank/blank”,因此一行中有三个空行,则它停止一行太晚。因此,唯一正确的结果是,如果第一对空行落在奇数/偶数行上。您如何使其符合OP的范围要求?谢谢。这个对我有用。我很难让它作为一行程序运行,所以我不得不在sed脚本中将它分散在几行上。当我尝试将其作为一个单行程序时,我得到了一个错误:“在D命令的末尾有额外的字符”。但当我将每个命令放在自己的行上时,它确实起了作用。你知道为什么吗?我刚刚注意到这个脚本在碰到双空行后停止工作。理想情况下,我希望它继续扫描文件,寻找下一个类似的模式。前几天有人犯了类似的错误。我不知道它是否与某种奇怪的Unicode代码有关。您是复制并粘贴了该命令还是键入了该命令?如果是前者,请尝试手动键入,看看是否出现相同的错误。哦,对不起,在你的问题中,你说了“停止打印”。你是对的,我应该写“停止打印该范围,但继续扫描下一个范围”--我将编辑我的问题。您需要
s/\n\n$/
否则它只打印TODO行,而不打印TODO块的其余部分。@Jeff谢谢。我不知道我在想什么,但我已经重写了我的解决方案,而不是错误的解决方案。如果您刚刚完成了我的修复,您的代码高尔夫分数会更高;-)此外,它还有一个优点,即通过在替换项中添加\n或-,可以轻松修改为打印一个或两个尾随空白。但是我从你的新东西中学到了一些东西,所以我很高兴。另外,我认为你不需要第二个脚本中的:b:o)@Jeff谢谢我最初将第二个regexp作为正数,并将其减少为负数,但忘记删除占位符。
sed -n '/TODO/{:a;N;/\n\n$/s//\n/p;Ta}' file
cat >tricky_todo.txt <<EOF
TODO block 1 line 1 (last line)


THIS LINE SHOULDN'T BE PRINTED #1
THIS LINE SHOULDN'T BE PRINTED #2
TODO block 2 line 1
     block 2 line 2
     block 2 line 3
     block 2 line 4

     block 2 line 6
     block 2 line 7
     block 2 line 8 (last line)


TODO block 3 line 1
     block 3 line 2
     block 3 line 3
     block 3 line 4
     block 3 line 5 (last line)


TODO block 4 line 1
     block 4 line 2
     block 4 line 3
     block 4 line 4
     block 4 line 5 (last line)


THIS LINE SHOULDN'T BE PRINTED #3
THIS LINE SHOULDN'T BE PRINTED #4
EOF
TODO block 1 line 1 (last line)


THIS LINE SHOULDN'T BE PRINTED #1
TODO block 2 line 1
     block 2 line 2
     block 2 line 3
     block 2 line 4

     block 2 line 6
TODO block 3 line 1
     block 3 line 2
     block 3 line 3
     block 3 line 4
     block 3 line 5 (last line)


TODO block 4 line 1
TODO block 1 line 1 (last line)
TODO block 2 line 1
     block 2 line 2
     block 2 line 3
     block 2 line 4

     block 2 line 6
     block 2 line 7
     block 2 line 8 (last line)
TODO block 3 line 1
     block 3 line 2
     block 3 line 3
     block 3 line 4
     block 3 line 5 (last line)
TODO block 4 line 1
     block 4 line 2
     block 4 line 3
     block 4 line 4
     block 4 line 5 (last line)