1

I have a unix file like below

abcdge
efg
bh

ggh
bhj
mkl

I want to change the file and make it like:

abcdge
efg
bhggh
bhj
mkl

means: after each blank line, the next line should be append with previous line. How can i achieve it?

3
  • George I have edited your question for readability but I'm not entirely sure I understand your question. Can you please just ensure my edits are correct. Thanks and sorry if they aren't. FYI please see the help section for information on asking questions.
    – jesse_b
    Nov 13, 2019 at 22:09
  • 1
    @Jesse_b It seems to me that "after each blank file," should be "after each blank line," Nov 13, 2019 at 22:17
  • @guillermochamorro: Thanks, I agree.
    – jesse_b
    Nov 13, 2019 at 22:34

4 Answers 4

3
$ sed -e '
    $!N;$q;N
    s/\n\n//
    P;D
 ' file

Maintain 3 lines inn the pattern space and remove the consecutive newlines when seen.

2

This will work using any awk in any shell on every UNIX box:

$ awk '1;END{print"\n"}' RS= ORS= file
abcdge
efg
bhggh
bhj
mkl
9
  • 1
    Can you explain it, what does 1, mean?
    – Prvt_Yadav
    Nov 15, 2019 at 15:11
  • It's the extremely common awk idiom of specifying a true condition to invoke the default action of printing the current record. It's equivalent to writing {print $0} and you'll find it used in many, many awk scripts.
    – Ed Morton
    Nov 15, 2019 at 15:13
  • awk '1' RS= ORS= file; echo appears to work just as well
    – bu5hman
    Nov 15, 2019 at 17:10
  • @bu5hman ok but there's no point adding additional commands and if you were going to pipe that output to some other command then it gets complicated and you have to consider which shell constructs to use and if you want it to run in a subshell or not, etc. If you can do it simply in one command then just do that.
    – Ed Morton
    Nov 15, 2019 at 17:23
  • Was only an observation, and perhaps a little golf, but I did like your awk use.
    – bu5hman
    Nov 15, 2019 at 17:28
1

If I understand you, maybe this is what you are looking for:

sed -z 's/\n\n//g' file

Output:

abcdge
efg
bhggh
bhj
mkl
2
  • 2
    Quite clever, although it's good to know possible limitations. I think this approach makes sed read and process any text file as one "line". This may be sub-optimal (or fail?) if the file is huge. And the command cannot be used as a real-time filter for a "neverending" text stream. Nov 14, 2019 at 1:24
  • Right and it should be stated that it's GNU sed only.
    – Ed Morton
    Nov 15, 2019 at 14:45
0
<file awk '
   {
   if (n && $0!="")
      printf "\n"
   if ($0=="")
      n=""
   else
      {n=1; p=1; printf "%s", $0;}
   }
   END {if (p) printf "\n"}
 '

Each non-empty line is printed without its terminating newline character. Before this happens, if the current line is not empty and the previous line was not empty, a newline character gets printed; so in these circumstances the previous line becomes complete.

Finally, if any non-empty line was printed, one newline character terminates the last incomplete line and makes it complete.

n and p are markers indicating "non-empty last line" and "something was printed" respectively.

Consecutive empty lines are equivalent to one empty line. I don't know if this behavior is what you want.

The solution should work well as a filter (i.e. in a pipe). If you need it to modify the input file, check this: Save modifications in place with awk.

1
  • Always use print "" instead of printf "\n" as the former just uses whatever value ORS has while the latter is hard-coding the value that ORS is assumed to have. And it saves you 3 chars :-).
    – Ed Morton
    Nov 19, 2019 at 17:40

You must log in to answer this question.

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