36

我找到了这个关于如何删除三重空行的问题和答案。但是,我只需要双空行。IE。所有双空行应完全删除,但应保留单个空行。

我知道一点 sed,但是删除三个空白行的建议命令在我头上:

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

4

8 回答 8

72

这会更容易cat

cat -s
于 2013-04-22T07:45:22.433 回答
19

我评论了sed你不明白的命令:

sed '
    ## In first line: append second line with a newline character between them.
    1N;
    ## Do the same with third line.
    N;
    ## 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.
    P;
    D
'

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

一个测试:

内容infile

1


2
3

4



5

6


7

运行sed命令:

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

这会产生:

1
2
3

4

5

6
7
于 2012-09-26T10:41:23.027 回答
8
sed '/^$/{N;/^\n$/d;}'

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

通常 sed 将读取一行。N将第二行附加到模式空间。如果该行是空行。这两行由换行符分隔。

/^\n$/这种模式将匹配那个时间,只有d会起作用。否则d不行。d用于删除模式空间的全部内容,然后开始下一个循环。

于 2012-09-28T06:19:23.567 回答
7

这会更容易awk

awk -v RS='\n\n\n' 1
于 2012-09-26T10:47:20.333 回答
1

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

sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' filename
于 2019-02-28T12:50:51.760 回答
0

据我所知,这里的解决方案都不起作用。cat -s正如@DerMike 所建议的那样,它不符合POSIX(如果您已经在使用sed另一个转换,那么它就不那么方便了),并且sed 'N;/^\n$/d;P;D'正如@Birei 所建议的那样,有时会删除比应有的更多的换行符。

相反,sed ':L;N;s/^\n$//;t L'有效。对于 POSIX 合规性 use sed -e :L -e N -e 's/^\n$//' -e 't L',因为 POSIX 没有指定 using;来分隔命令。

例子:

$ 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     
                qux
qux     quxx    
                quxx
                
                
quxx            
$ 

在这里,我们可以并排查看原始文件、@Birei 的解决方案和我的解决方案。@Birei 的解决方案删除了​​所有分隔bazand的空白行qux,而我的解决方案按预期删除了除一个之外的所有行。

解释:

: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.

于 2022-01-13T10:29:36.510 回答
-1

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

sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' 文件名

于 2019-02-28T13:00:54.717 回答
-2

只需将其通过管道传递到“uniq”命令,所有空行,无论它们的数量如何,都将缩减为一个。越简单越好。

澄清:正如 Marlar 所说,如果您不想删除“其他非空白连续重复行”,这不是一个解决方案。这其他情况下的解决方案,例如尝试清理配置文件时,这是我看到这个问题时所寻求的解决方案。我确实只是使用'uniq'解决了我的问题。

于 2013-10-07T09:34:30.263 回答