Skip to content

Removing blank lines in a buffer

by mickey on March 16th, 2011

This is a frequent question so I figured I’d mention the solution here:

You want to remove all empty (blank) lines from a buffer. How do you do it? Well, it’s super easy.

Mark what you want to change (or use C-x h to mark the whole buffer) and run this:

M-x flush-lines RET ^$ RET

And you’re done. So what does that mean? Well, M-x flush-lines will flush (remove) lines that match a regular expression, and ^$ contain the meta-characters ^ for beginning of string and $ for end of string. Ergo, if the two meta-characters are next to eachother, it must be a blank line.

We can also generalize it further and remove lines that may have whitespace (only!) characters:

M-x flush-lines RET ^\s-*$ RET

In this case \s- is the syntax class (type C-h s to see your buffer’s syntax table) for whitespace characters. The * meta-character, in case you are not a regexp person, means zero or more of the preceding character.

Update — Pete Wilson asks: “How do you collapse multiple lines into one blank line?”.

That’s a bit harder, mostly because flush-lines only works well on whole, single lines. For multi-line processing you have two choices: you can abuse regexp, or you can use a macro. It’s fairly easy to do it with regexp in this case, but for more complex data-scrubbing I would use a macro; nevertheless, I will do it both ways*.

*I’m pretty sure my macro/regexp examples are general enough to work in all cases; but let me know if they aren’t

For the regexp approach I will use C-M-% (query-replace-regexp) and because I have to use a literal newline character I will use Emacs’s quoted-insert command, bound to C-q. So to insert a newline, you would type C-q C-j.

The ^J represents the literal newline or line feed character (see ASCII Control Characters on Wikipedia for more information).

So the text we want to search for looks like this:

Search For: ^^J\{2,\}

Replace With: ^J

So how does it work? Well, we tell Emacs to search for any two or more newlines that are at the beginning of a string — where each line is considered a string by Emacs — and because we search for two or more we skip the ones that only have a single newline. So if there are 10 newlines in a row, we replace them all in one fell swoop with a single newline. You can omit the replacement newline to remove them altogether!

The other way is very similar and uses a keyboard macro, C-M-r and delete-blank-lines bound to C-x C-o. This approach is more complicated than it really ought to be, because delete-blank-lines will annoyingly (in this case — it’s a useful feature otherwise!) convert multiple blank lines into a single blank line (good), and remove single blank lines altogether (bad.)

To make the macro, go to the end of the buffer M->, press F3 to begin recording, and then type C-M-r and in the isearch prompt enter:

Regexp ISearch backward: ^^J\{2,\}

Press return to go to the first match and press C-x C-o. Now press F4 to stop recording and you’re done with the macro. Press C-u C-x e to fix all remaining instances, and that’s it — you’re done.

Exercise to the reader: Why did I search in reverse with C-M-r instead of using C-M-s?

14 Comments
  1. Pete Wilson permalink

    Nice tip! But, how do you collapse multiple blank lines into one blank line?

    • mickey permalink

      Pete,

      I updated the blog article with two different ways of solving the problem.

      Mickey.

      • ozan permalink

        You can also do it by C-x C-o

        • mickey permalink

          Hi ozan,

          That is not quite the same as C-x C-o will only work on the area around point; and if there happens to only be one empty line then that line is removed, which is not what we want.

  2. In the early 80′s, i wrote a filter in C called ‘onespc’ (V7 Unix had 14 char filenames, i tended to omit vowels). ‘onespc’ by default would read stdin, compress groups of blank lines (with optional white space) to a single blank line, and write to stdout. I’d use it from the command line, sometimes in scripts that changed many files. I’d use it from Emacs on the whole buffer or regions. ‘onespc’ has a bunch of options to do similar things, like remove all blank lines.

    Emacs was sluggish starting up until the 386/33 or 486/25. This may be ancient history, but it was over a decade for me. I haven’t come up with a good way to use Emacs to edit hundreds of files. My current plan is to learn elisp. That should fix everything. Lisp isn’t easy to learn. But i’ve used Lisp and scheme in the past.

    In the late 80′s, i wanted something easier in scripts than

    for i in *.txt; do
    onespc $i > x
    mv x $i
    done

    It’s not a good solution, since x might exist as a file. So, i wrote a version of ‘into’. The syntax is

    for i in *.txt; do
    onespc $i | into $i
    done

    So, ‘into’ copies stdin to a temp named file, which it determines does not exist in advance. On EOF, it renames it to the argument, deleting the existing file if it can.

    I was about to publish all these utilities, but then someone publish the ‘getopt’ functions for command line. I liked my least ambigous command line parser better. I never liked the ‘–’ standard. I stalled.

    Who knows? Maybe Emacs has a simple file mapper. I’d like to be able to do this easily:

    for i in find . $HOME/some/other/place -type f -name \*.txt; do
    onespc $i | into $i
    done

    But ‘find’ and my filter set (including all of the *ix filters, including ‘sed’ and ‘perl’) is a pretty powerful set of flexibility to allow.

    Despite emacs’s internal docs, ‘info’, ‘man’, and google, i can’t always find docs for what i want to do just at this moment.

    • mickey permalink

      Stephen,

      Thanks for the backstory.

      Elisp is really not that difficult to learn, as the language syntax is actually very simple. I think you’ll have a harder time learning all the different ways of doing stuff as Emacs has several ways of doing things (some of them the right way; some of them not.)

      Anyway, to answer your question: there’s a few cool ways of doing it that touch on stuff I haven’t mentioned it before — so challenge accepted!

      I’ll write about it in a couple of days.

      Regards,

      Mickey.

  3. piyo permalink

    Is M-x delete-blank-lines available on your Emacs? I verified I can use it on Gnu Emacs 22.3.

    • mickey permalink

      It is indeed, piyo, and it is very useful when you’re editing text but not so good if you want to remove all the blank lines in a buffer as it only acts on lines around point. My example in the article where I used a macro I did use delete-blank-lines.

  4. Sameer Morar permalink

    Herewith two functions to do what you’ve described in this article:

    (defun flush-blank-lines ()
    “Removes all blank lines from buffer or region”
    (interactive)
    (save-excursion
    (let (min max)
    (if (equal (region-active-p) nil)
    (mark-whole-buffer))
    (setq min (region-beginning) max (region-end))
    (flush-lines “^ *$” min max t)
    )
    )
    )

    (defun collapse-blank-lines ()
    “Collapse multiple blank lines from buffer or region into a single blank line”
    (interactive)
    (save-excursion
    (let (min max)
    (if (equal (region-active-p) nil)
    (mark-whole-buffer))
    (setq min (region-beginning) max (region-end))
    (query-replace-regexp “^
    \\{2,\\}” ”
    ” nil min max)
    )
    )
    )

    Any suggestions on improving these?

    • mickey permalink

      Sameer,

      Not bad for a first attempt! I think the first one can be simplified to this:

      This way we use Emacs’s built-in support for working with regions by using the interactive “r” code letter which will pass in the start/end of point and mark automatically — this is important for people who don’t use transient-mark-mode. This approach also lets use pass in explicit ranges from lisp.

      The second function works in much the same way as the first, although I have opted to use the interactionversion instead of the “proper” elisp regexp function:

      • Sean permalink

        Actually, mickey I do not see the same behavior with your flush-blank-lines and sameer’s. If I run yours without first marking a region it starts at point, not point-min.

        • mickey permalink

          Hi Sean,

          That is correct behaviour as far as Emacs is concerned (whether it is sensible is another debate…)

          Before transient-mark-mode came about Emacs would work from point “onwards” to the end of the buffer or the end of the mark. This effect is still present in Emacs hence its slightly annoying “two-tier” region system.

          The solution is to either C-x h first to mark the region or alter the function to work on the entire region.

          Mickey.

  5. onano permalink

    > Why did I search in reverse with C-M-r instead of using C-M-s?

    To save a C-p.

  6. Christian Weiske permalink

    Thanks.

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS