39

I know there is a similar question in SO How can I replace mutliple empty lines with a single empty line in bash?. But my question is can this be implemented by just using the sed command?

Thanks

Community
  • 1
  • 1
Just a learner
  • 26,690
  • 50
  • 155
  • 234
  • Try reading all the answers next time: http://stackoverflow.com/questions/922449/how-can-i-replace-mutliple-empty-lines-with-a-single-empty-line-in-bash/922499#922499 – OrangeDog Dec 23 '10 at 17:47
  • 3
    Actually I have read all the answers. The answer Clue Less and Can Berk Güder provided are just remove all empty lines, not the same as what I needed. – Just a learner Dec 23 '10 at 17:57
  • *-i* switch? *sed -i '/^$/d' text.txt* should work and as far as i've checked it _is_ in answer list (besides *-i* option). – barti_ddu Dec 23 '10 at 18:21
  • 2
    @barti_ddu: this will delete _all_ empty lines, rather than reduce them into one. – thkala Dec 23 '10 at 18:29

3 Answers3

77

Give this a try:

sed '/^$/N;/^\n$/D' inputfile

Explanation:

  • /^$/N - match an empty line and append it to pattern space.
  • ; - command delimiter, allows multiple commands on one line, can be used instead of separating commands into multiple -e clauses for versions of sed that support it.
  • /^\n$/D - if the pattern space contains only a newline in addition to the one at the end of the pattern space, in other words a sequence of more than one newline, then delete the first newline (more generally, the beginning of pattern space up to and including the first included newline)
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • +1 Anyway, your example is better, since it will process leading & trailing empty lines correctly, while mine will simply strip them. – barti_ddu Dec 23 '10 at 20:55
  • Matching newline at the beginning of the line is not necessary, simply matching newline is enough. – barti_ddu Dec 24 '10 at 01:56
  • would someone please explain the sed expression? – ThorSummoner May 15 '20 at 21:12
  • 2
    expression: `/.../` match lines via regexp, `^$` regex match empty line (beginning of line followed by end of line) `N` append next line to current line, so now we should have a blank line a newline and another blank line `;` I didn't find anything about this in the manual, maybe this means "branch if line matches" eg "do the next command for double empty lines", `/^\n$/` regex match empty line newline empty line and use D command, which I think deletes the selection even if it contains newlines – ThorSummoner May 15 '20 at 21:30
  • this also appears to work with the original input buffer and not with a post-substituted buffer? I cant seem to combine it like `sed -e s,\ \+,,g -e /^\$/N\;/^\\n\$/D < data` – ThorSummoner May 15 '20 at 21:34
4

You can do this by removing empty lines first and appending line space with G command:

sed '/^$/d;G' text.txt

Edit2: the above command will add empty lines between each paragraph, if this is not desired, you could do:

sed -n '1{/^$/p};{/./,/^$/p}'

Or, if you don't mind that all leading empty lines will be stripped, it may be written as:

sed -n '/./,/^$/p'

since the first expression just evaluates the first line, and prints it if it is blank.

Here: -n option suppresses pattern space auto-printing, /./,/^$/ defines the range between at least one character and none character (i.e. empty space between newlines) and p tells to print this range.

barti_ddu
  • 10,179
  • 1
  • 45
  • 53
0

Since "empty lines" can contain "invisible" whitespaces, tabs, \f, \v, \r, etc.; in more general contexts we can use

sed -zE 's/([ \t\f\v\r]*\n){3,}/\n\n/g' inputfile
lezambranof
  • 141
  • 1
  • 5