Why can't I sed two [or more..] empty lines to one empty line? What is the trick?

echo -e "hello\n\n\nhello2" | sed 's/^$\n^$/\n/g'


3 Answers 3


The reason your sed failed is that unless you specify a multi-line operator, it operates on the stream one line at a time. Multiple beginning of line ^ and end of line $ operators are meaningless when strung together like that if you are only looking at the text one line at a time.

The easist way to collapse multiple blank lines is with cat. From the man page:

-s, --squeeze-blank
suppress repeated empty output lines

It works like this:

$ echo -e "hello\n\n\nworld" | cat -s


If you want to remove the blank lines entirely rather than compressing them, use grep:

$ echo -e "hello\n\n\nworld" | grep -v '^$'

Note that if you really want to do this in sed you have to use complicated expressions and actions. Here is an example (thanks to fred) that collapses any number of sequencial blanks into a single blank line:

$ echo -e "hello\n\n\nworld" | sed -re '$!N;/^\n$/!P;D'


You can see why cat -s is a good deal easier if collapsing multiple blank lines is all you are after!

  • 1
    you're a real living god. Aug 6, 2011 at 12:20
  • 2
    @LanceBaynes: Nope, just a man who's had the same question and read enough other people's code to notice the answers.
    – Caleb
    Aug 6, 2011 at 12:23
  • 1
    Here is O'Reilly's Command Summary for sed
    – Peter.O
    Aug 6, 2011 at 14:22
  • echo -e "hello\n\n\nworld\n\n" no work.
    – John Chen
    Oct 31, 2021 at 4:48

An alternative using awk for posterity which allows you to more control is something like:

cat file | awk 'BEGIN {sp=0} \
         {if (length($0)==1) {sp=sp+1} \
          if (sp>=1&&length($0)==1) {
          } else {
             for (i=1;i<=((3<sp)?3:sp);i++) {print ""}
             print $0; sp=0}

This compresses any number of lines of space (length($0)==1) into fewer, but not necessarily zero (3 in this case).

So 1, 2, or 3 lines of blank space will be preserved, but more than 3 will always be compressed to 3.


sed -e '/./b' -e :n -e 'N;s/\n$//;tn' infile

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .