如何使用sed只删除双空行?

38 人关注

I found this 问答 关于如何删除三倍空行的问题。然而,我只需要对双空行有同样的要求。也就是说,所有的双空行应该被完全删除,但单空行应该被保留。

我知道一点sed,但建议的删除三倍空行的命令超出了我的想象。

sed '1N;N;/^\n\n$/d;P;D'

2 个评论
三倍和更多的空行呢?
@xdazz: 是的,对于三倍或更多的空行是可以的。
regex
linux
sed
marlar
marlar
发布于 2012-09-26
8 个回答
DerMike
DerMike
发布于 2013-10-07
已采纳
0 人赞同

有了 cat ,这就更容易了。

cat -s
    
不错,但它的作用并不完全一样。不过,我不知道这个选项,它非常有用,所以还是要感谢。
Birei
Birei
发布于 2013-10-07
0 人赞同

我已经评论了你不了解的 sed 命令。

sed '
    ## In first line: append second line with a newline character between them.
    ## Do the same with third line.
    ## When found three consecutive blank lines, delete them. 
    ## Here there are two newlines but you have to count one more deleted with last "D" command.
    /^\n\n$/d;
    ## The combo "P+D+N" simulates a FIFO, "P+D" prints and deletes from one side while "N" appends
    ## a line from the other side.

删除1N,因为我们在 "堆栈 "中只需要两行,有第二个N就够了,并将/^\n\n$/d;改为/^\n$/d;,删除所有连续的两行空白。

一个测试。

Content of infile:

Run the sed command:

sed '
    /^\n$/d;
' infile

这就产生了。

jan
对于所有想使用这个的人来说,别忘了 sed -i 选项,在文件中立即改变,而不是将结果发送到输出流。
在macOS上,这将删除文件的最后一行(即使该行不是空白)。
解释得很好,但词组部分可以更清楚。"这里有两个换行符,但你必须算上再删除一个",/^\n\n$/d;已经删除了3个空行。(注意3个空行有两个\n)最后一个'D'对'模式空间'进行操作。 D命令删除了模式空间,只留下一行(不含n)。-- 然后sed开始下一个循环,跳到开头,N所做的,是将n追加到模式空间然后加载下一行。
Manikandan Rajendran
Manikandan Rajendran
发布于 2013-10-07
0 人赞同
sed '/^$/{N;/^\n$/d;}'

它将只删除文件中连续的两个空行。你只能在文件中使用这个表达式,然后你才能完全理解。当一个空行出现时,它将进入大括号中。

通常情况下,sed会读取一行。N将附加第二行到模式空间。如果该行是空行,则两行之间用换行符分开。

/^\n$/这个模式将匹配,这时只有d会工作。否则d不会工作。替换代码3】是用来删除模式空间的全部内容然后开始下一个循环。

我试过这个命令,它删除了多余的换行符(有些多个换行符被完全删除,而不是被单个换行符取代)。我不太清楚为什么会发生这种情况,所以要小心。
sed 'N;/^\n$/D;P;D;'似乎效果更好,只删除了连续的新行。
Thor
Thor
发布于 2013-10-07
0 人赞同

有了 awk ,这就更容易了。

awk -v RS='\n\n\n' 1
    
user11130756
user11130756
发布于 2013-10-07
0 人赞同

但是,上述解决方案只删除了第一个搜索的3个连续空行。 要删除所有连续的3个空行,请使用以下命令

sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' filename
    
user17549713
user17549713
发布于 2013-10-07
0 人赞同

据我所知,这里的解决方案都不可行。@DerMike建议的 cat -s 不符合POSIX标准(如果你已经在使用 sed 进行另一种转换,它就不太方便),而@Birei建议的 sed 'N;/^\n$/d;P;D' 有时会删除更多的换行。

相反, sed ':L;N;s/^\n$//;t L' 就可以。为了符合POSIX标准,请使用 sed -e :L -e N -e 's/^\n$//' -e 't L' ,因为POSIX没有规定使用 ; 来分隔命令。

$ S='foo\nbar\n\nbaz\n\n\nqux\n\n\n\nquxx\n';\
> paste <(printf "$S")\
>       <(printf "$S" | sed -e 'N;/^\n$/d;P;D')\
>       <(printf "$S" | sed -e ':L;N;s/^\n$//;t L')
foo     foo     foo
bar     bar     bar
baz     baz     baz
qux     quxx    

这里我们可以看到原始文件、@Birei的解决方案和我的解决方案并排在一起。@Birei的解决方案删除了bazqux之间的所有空行,而我的解决方案则按计划删除了所有空行。

解释一下。

:L        Create a new label called L.
N         Read the next line into the current pattern space,
          separated by an "embedded newline."
s/^\n$//  Replace the pattern space with the empty pattern space,
          corresponding to a single non-embedded newline in the output,
          if the current pattern space only contains a single embedded newline,
          indicating that a blank line was read into the pattern space by `N`
          after a blank line had already been read from the input.
t L       Branch to label L if the previous `s` command successfully
          substituted text in the pattern space.

实际上,这一次删除了一个反复出现的空行,用N将每个空行作为嵌入式换行符读入模式空间,用s删除它们。

Darsh
Darsh
发布于 2013-10-07
0 人赞同

但是,上述解决方案只删除了第一个搜索的3个连续空行。要删除所有连续的3个空行,请使用以下命令