10

In Ed I can do a search to replace all blank lines as follows:

g/^$/d

This deletes all blank lines. But what if I wish to delete two or more blank lines and keep 1? For example:

Line 1


Line 2



Line 3

Becomes:

Line 1

Line 2

Line 3
2
  • 2
    Are all non-empty lines otherwise different from their immediate following line? If so, e !uniq % would be one solution... This requires you to first save your unsaved edits with w first though.
    – Kusalananda
    Jul 7, 2021 at 13:47
  • Interesting; tr can squeeze duplicate characters but a blank line to be left in requires two sequential newline characters.
    – Wildcard
    Jul 8, 2021 at 18:25

2 Answers 2

8

Adapted from the Vim Wiki:

ed -s file <<EOF
v/./.,/./-1j
w
q
EOF
  • v/./: select all lines that don't match the regex . (i.e., select all blank lines). Execute the following action on them:
    • .,/./-1j: the join command is applied from a selected line (.) up to the the line above the next non-blank line (/./-1).
  • w q: save and quit. You could use %p Q instead to only display the output without modifying the file.

Although equally valid, my original suggestion was more complicated:

printf '%s\n' 'g/^$/.,/./-1d\' 'i\' '' w q | ed -s file

This one uses two commands for a single global command (usually the command list consists of a single command), which requires prefixing newlines with backslashes for its command list.

  • g/^$/: select all blank lines.
    • .,/./-1d\: delete from the selected line (.) up to the line above the next non-blank line (/./-1). This would delete all blank lines, so
    • 'i\' '': insert a new blank line above.

It is equivalent to use here-docs or Printf to feed Ed. Just pick the one you like best.

Reference: POSIX Ed.

0
3

Using an external command is a totally valid way to edit in ed, and assuming that all non-empty lines are unique when compared to their immediately surrounding lines (i.e. non-repeating), we could call uniq to remove the excess empty lines:

w
e !uniq %

We need to save our work with w first since uniq will read from the current file on disk. The e !somecommand command replaces the contents of the editing buffer with the output of somecommand, and uniq will remove duplicated consecutive lines in the named file. The % in the command will be replaced by the name of the current file. With our assumption at the start, this solves our issue by removing duplicated consecutive empty lines.

5
  • 1
    I don't see any assumption that the lines are not repeated. So if the file is a\na\n\n\nb\n unique will change this to a\n\nb\n so missing a whole a\n.
    – icarus
    Jul 8, 2021 at 4:04
  • 1
    @icarus I made this assumption explicitly at the start: assuming that all non-empty lines are unique when compared to their immediately surrounding lines Maybe I should change the wording to "not repeated"?
    – Kusalananda
    Jul 8, 2021 at 6:45
  • Ah, I was looking for the assumption in the OP post. I am down voting this answer as I don't want to scan a 20GB file by eye to see if there are repeated lines.
    – icarus
    Jul 10, 2021 at 2:15
  • 1
    @icarus You're editing 20 GB files in ed?! You can scan that with uniq and grep first if you wish, instead of with your eyes: uniq -d file | grep '.' (if there's output, you need to go for a different solution).
    – Kusalananda
    Jul 10, 2021 at 5:28
  • I am partial to this solution for its simplicity.
    – Edman
    Jul 11, 2021 at 4:48

You must log in to answer this question.

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