如何在看到两个连续的空白行之前打印一系列行?

时间:2009-12-21 04:56:44

标签: sed

我想使用像这样的sed脚本

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

除了sed应该在遇到两个连续的空行后停止打印范围,而不是仅仅一个空白行。然后它应该继续扫描下一个感兴趣的范围。换句话说,感兴趣范围的结束由两个空行定义。我甚至不确定地址范围是否可以处理这种要求,所以如果还有其他方法可以解决这个问题,请告诉我。

6 个答案:

答案 0 :(得分:6)

当遇到两个连续的空白行时,无论空白行与非空行的奇数/偶数配对如何,这都应该停止:

不要打印两个空行:

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的(OP)评论和编辑的要求,这似乎可以找到一个范围内的模式,该范围以两个空白行结尾,在文件中多次:

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

答案 1 :(得分:1)

使用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

答案 2 :(得分:1)

请勿使用地址范围

相反,寻找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

@Paused的sed脚本的输出

不幸的是,获得地址范围来完成此任务几乎是不可能的。多余的行太多,而不是所有所需的行:-(

sed -n '/^TODO/,/^$/{H;N;/^\n$/{b};p}' <tricky_todo.txt
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块是文件中的最后一个内容,则它必须以OP中指定的两个空行结尾,否则它将被删除。 / p>

sed -n '/^TODO/{:a;N;s/\n\n$//;Ta;p}' <tricky_todo.txt
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)

帽子到@potong的提示

FWIW,当我想到上面的脚本时,我以某种方式忽略了potong的原始答案(有一个小缺陷)。当我提到它时,potong使用其他策略完全重写了该答案。由于这个原因和我脚本的警告,我将在此处包括potong原始答案的更正版本:

sed '/^TODO/!d;:a;$!{N;s/\n\n$//;t;ba}' <tricky_todo.txt

一种“笨拙”的解决方案?

Awk当然功能强大,但是我个人倾向于使用sed,因为它更像是我每天使用的心爱的vi。不过,我们开始:

awk -vRS="\n\n\n" -vFS="\n" '/TODO/{s=0;for(n=1;n<=NF;n++){if(s==1||$n~/^TODO/){print $n;s=1}}}' <tricky_todo.txt

答案 3 :(得分:0)

sed 'N;/^\n$/q;P;D'

概念证明

$ cat double_blank.txt
foo
bar

baz


blah
one
two

three

结果

$ sed 'N;/^\n$/q;P;D' double_blank.txt
foo
bar

baz


答案 4 :(得分:0)

以SiegeX的答案为基础:

cat > lines <<'EOF'
a


c
d
EOF
sed '/^$/N; /^\n$/q' lines

答案 5 :(得分:0)

这可能对您有用:

sed '/^TODO/!d;:a;$!{N;s/\n$//;t;ba}' file