Replace blank line with above line content

Here is one way with awk (p holds the previous line when NF is zero).

awk 'NF {p = $0} {print p}' file

When the line is not empty, we store the line into p (for future use) and print p.

When NF==0 (for empty lines) we only print p.


In awk (note that this one will print any empty lines that come before the first non-empty one):

$ awk '{ if(! NF){$0=last}else{last=$0;}}1' file
101 abc group1
765 efg group2 
345 hij group4 
345 hij group4 
456 gfd group9 
762 ert group7 
762 ert group7 
762 ert group7 
554 fgt group11  

Explanation:

NF holds the number of fields. If the line is empty, there are no fields so the variable will be 0.

  • if(! NF){$0=last}: if the number of fields is 0 (empty line), set the current line ($0) to the value of the variable last.
  • else{last=$0;}: if there are fields, so this line is not empty, set last to hold the contents of this line.
  • 1: the lone one at the end is an awk trick: when something evaluates to true (1 or any other integer greater than 0 is always true, since 0 is false) awk will print the current line. So that 1 is equivalent to print $0.
$ awk '! NF ? $0=last : last=$0;' file
101 abc group1
765 efg group2 
345 hij group4 
345 hij group4 
456 gfd group9 
762 ert group7 
762 ert group7 
762 ert group7 
554 fgt group11  

Explanation This is the same idea as above, but written in a more concise way. We are using the ternary operator. Since one of the two conditions will always be true (either NF is true or it is not true, so the ternary operator will always return true), both outcomes result in the line being printed (except for cases where the line is empty and no non-empty lines have been seen or if a line consistes of nothing but 0). However, if NF is not set, we set $0 to last and if it is set, we set last to $0. The result is the output we want.

Since the above will not print lines that are just 0, you can use this instead of that is a problem for you:

awk '{! NF ? $0=last : last=$0};1' file

Using the supplied input and sed:

$ sed -n '/^$/{g;};h;p' infile
101 abc group1
765 efg group2
345 hij group4
345 hij group4
456 gfd group9
762 ert group7
762 ert group7
762 ert group7
554 fgt group11 
$

Note: '/^$/{g;};h;p' is obviously more commonly/properly written as '/^$/g;h;p'. Just a style of mine!

As guest_7 pointed out (thank you), the sed command can also be written more simply as sed '/^$/g;h' infile

As terdon pointed out, and something I did not think initially, the "empty" lines may contain blank spaces or tabs (whitespaces). In that case, a more robust solution would be:

$ sed '/^\s*$/g;h' infile

and a more portable solution supporting the various locales is:

$ sed '/^[[:blank:]]*$/g;h' infile