【问题标题】:How to use sed to remove only double empty lines?如何使用 sed 仅删除双空行?
【发布时间】:2022-01-13 18:47:21
【问题描述】:

我发现这个question and answer 关于如何删除三个空行。但是,我只需要双空行。 IE。所有双空行应完全删除,但应保留单个空行。

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

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

【问题讨论】:

  • 三个或更多的空行呢?
  • @xdazz: 是的,三个或更多空行都可以。

标签: regex linux sed


【解决方案1】:

使用cat 会更容易:

cat -s

【讨论】:

  • 不错,但它的作用并不完全相同。但是,我不知道这个选项,它非常有用,所以还是谢谢。
【解决方案2】:

我评论了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

【讨论】:

  • 对于所有想要使用它的人,不要忘记 sed -i 选项立即在文件中更改它,而不是将结果发送到输出流。
  • 在 macOS 上,这会删除文件的最后一行(即使该行非空白)
  • 很好的解释,但正则表达式部分可以更清楚。 “这里有两个换行符,但你必须再算一个删除”,/^\n\n$/d;已经删除了 3 个空行。(注意 3 个空行有两个 \n)最后一个“D”对“模式空间”进行操作。 D-命令删除模式空间并只留下一行(没有 \n)。 -- 然后 sed 开始下一个循环,跳到开头,N 的作用是将 \n 附加到模式空间然后加载下一行。
【解决方案3】:
sed '/^$/{N;/^\n$/d;}'

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

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

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

【讨论】:

  • 我试过这个命令,它删除了多余的换行符(多个换行符中的一些被完全删除,而不是被单个换行符替换)。我不太确定为什么会发生这种情况,所以要小心。
  • sed 'N;/^\n$/D;P;D;'似乎效果更好,只删除连续的换行符
【解决方案4】:

使用awk 会更容易:

awk -v RS='\n\n\n' 1

【讨论】:

    【解决方案5】:

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

    sed '1N;N;/^\n\n$/ { N;s/^\n\n//;N;D; };P;D' filename
    

    【讨论】:

      【解决方案6】:

      据我所知,这里的解决方案都不起作用。 @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     
                      qux
      qux     quxx    
                      quxx
                      
                      
      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 删除它们。

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

        • 我了解到您已经创建了 2 个帐户。现在我建议你保留另一个并删除那个。提示:您可以在创建后更改帐户名称
        【解决方案8】:

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

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

        【讨论】:

        • 不过,有时它可能太简单了!如果源包含重复条目,它们也会被删除。这不是一个可接受的解决方案。
        猜你喜欢
        • 2011-06-06
        • 2015-02-15
        • 2013-05-01
        • 2011-05-11
        • 2012-09-04
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多