56

Question more or less says it all. I'm aware that /^$/d will remove all blank lines, but I can't see how to say 'replace two or more blank lines with a single blank line'

Any ideas?

6 Answers 6

67

If you aren't firing vim or sed for some other use, cat actually has an easy builtin way to collapse multiple blank lines, just use cat -s.

If you were already in vim and wanted to stay there, you could do this with the internal search and replace by issuing: :%s!\n\n\n\+!^M^M!g (The ^M is the visual representation of a newline, you can enter it by hitting Ctrl+vEnter), or save yourself the typing by just shelling out to cat: :%!cat -s.

4
  • wow, did not know the -s option of cat - just a historic note, it is not in POSIX, but seems to be available in BSD and GNU cat. May 7, 2011 at 20:40
  • 5
    Marking as 'winning' for the :%!cat -s. Learn something GNnew everyday! May 7, 2011 at 20:43
  • 4
    I think you can also use \r instead of ^M like this: %s!\n\n\n\+!\r\r!g May 28, 2017 at 22:32
  • I use a technique like this using the fmt command to do hard word wrapping on text and unexpand to convert spaces to tabs. Feb 16, 2021 at 6:08
23

Use \n to indicate a newline in the search pattern. Use Ctrl+M in the replacement text, or a backreference. See :help pattern and :help sub-replace-special (linked from :help :s).

%s/\(\n\n\)\n\+/\1/
6
  • Can you please explain how does the search pattern?
    – Sagar Jain
    Sep 22, 2015 at 7:14
  • @sjmp Requirement: replace two or more blank lines with a single blank line. Implementation: replace three or more consecutive newlines with just two newlines. See the manual for an explanation of the constructs used in the command. Sep 22, 2015 at 8:21
  • But why do you need to use a group when its contents are fixed?
    – Sabuncu
    Nov 23, 2017 at 18:01
  • 1
    @Sabuncu You don't need to use a group. But why not use a group? Here, I used a group because you can't copy-paste a command with a newline in the replacement text: you need to insert a literal Ctrl+M character, \n doesn't work in the replacement text. Nov 23, 2017 at 19:24
  • Now I understand, thank you for taking the time to answer.
    – Sabuncu
    Nov 23, 2017 at 19:52
8

If in Vim, just do this:

:%!cat -s

The -s flag for cat squeezes multiple blank lines into one.

2
  • 3
    You might want to add a little detail around how this works, even if it is just a quote from the man page.
    – jasonwryan
    Nov 21, 2012 at 5:22
  • Didn't work on windows 7
    – user674669
    Dec 2, 2017 at 2:31
1

Using Perl:

perl -00 -pe ''

-00 command line option turns paragraph slurp mode on, meaning Perl reads text paragraph by paragraph rather than line by line.

0

With sed (GNU sed) 4.2.2:

sed -r '
  /^\s*$/ { 
    # blank line
:NEXT
    N # append next line to pattern space - if none, autoprint PS and exit
    s/^\s*$\n^\s*$//g;t NEXT # if 2 blank lines, clear PS and loop to NEXT
  }
  # else, autoprint PS and next/exit
' < $MYFILE
-4

I know this is silly code, but I wanted to solve this issue in less than 10 min, and it worked

for file in /directory/*
do
  originalname=$file
  us='_'
  tempname=$file$us
  echo $originalname
  mv $originalname $tempname
  uniq $tempname $originalname
  rm $tempname
done
4
  • 1
    uniq removes adjacent equal lines. Which is not what OP wants.
    – pacholik
    Mar 30, 2017 at 9:01
  • @pacholik he clearly said "Replacing Multiple blank lines with a single blank line" NOT remove adjacent equal lines!!! Mar 30, 2017 at 17:43
  • 3
    Yes, exactly...
    – pacholik
    Mar 31, 2017 at 7:17
  • 1
    This does more than remove multiple blank lines - it removes all repeating lines.
    – shalomb
    May 14, 2021 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.