views:

89

answers:

5

Hi all,

I am learning to use sed and have a hypothetical requirement:

bash$ cat states
California


Massachusetts


Arizona

Wisconsin

I would like the output: (Basically I want only one blank line in between)

California

Massachusetts

Arizona

Wisconsin

Please suggest ways to do it with sed. Should it use concept of multiline pattern space etc.

Thanks,

Jagrati


In response to one of the comments, Ok, I ran some test scripts, and I was wrong with hypopthesis that address space selection criteria is applied only once. It seems to get activated again and again.

bash$ cat file 
a 
b 
c 
a 
b 
c 

bash$ sed -e '/a/,/b/s/$/x/g' file 
ax 
bx 
c 
ax 
bx 
c 

I had the impression that it would yield:

ax 
bx 
c 
a 
b 
c

So could someone please explain how the sed proceeds in case of comma separated address spaces.

+3  A: 

Try this it will delete all consecutive blank lines

cat states | sed '/./,/^$/!d'

outputs:

California

Massachusetts

Arizona

Wisconsin
dalton
useless use of cat.
ghostdog74
It works, but can't quite understand how.. this uses comma separated addresses. 2nd address means a blank line. The first address means any single character. and then it deletes lines not matching this criteria. But isn't the address space selection applied only once. So how is it able to get rid of 2 blank lines between Massachusetts and Arizona.. Could you please explain how it's working..
learnerforever
Ok, I ran some test scripts, and I was wrong with hypopthesis that address space selection criteria is applied only once. It seems to get activated again and again.bash$ cat fileabcabcbash$ sed -e '/a/,/b/s/$/x/g' fileaxbxcaxbxcI had the impression that it would yield:axbxcabc
learnerforever
A: 

you can use awk as well

$ cat file
California


Massachusetts


Arizona

Wisconsin

$ awk 'NF{print;print ""}'  file
California

Massachusetts

Arizona

Wisconsin
ghostdog74
+1  A: 

I know the OP explicitly asked for a solution using sed and/or awk, but the problem could also be solved with just cat:

cat -s file

Otherwise, here is yet another way to solve the problem with sed:

sed '/./!d; G' file

which exploits G to append an empty line to all non-empty lines found in files.

marco
just a small note that this inserts blank line after the last line as well, but of course that can be taken care, bysed -e '/./!d' -e '$!s/$/\> /' statesSo your basic idea of doing it in 2 passes basically works.
learnerforever
+1  A: 

This can be accomplished without sed, but also without meeting your requirement of learning sed:

cat -s states

It's interesting to note that the three examples for doing this given in info sed for GNU sed are each much more complex than dalton's and marco's answers.

Here are those versions condensed into one-liners:

sed ':x;/^\n*$/{N;bx};s/\n*/\n/' states

sed '1,/^./{/./!d};:x;/./!{N;s/^\n$//;tx}' states

sed -ne '/./!d;:x;p;n;/./bx;:z;n;/./!bz;i\ ' -e 'bx' states
Dennis Williamson
Only the last of these 3 examples works. The 1st one inserts extra blank lines before the first line, and the 2nd one leaves no blank line between California and Massachusetts.
learnerforever
+1 for a correct answer that *only* uses `cat` -- I don't think I've ever seen that before :)
Mark Rushakoff
@learnerforever: I should have included the information from the `info` file which mentions leading and trailing blank lines. The missing blank line is a bug in their script! Changing the `1` to a `0` (GNU `sed` only) seems to fix that problem. The first one seems to be improved by adding `1!` right before the `s`.
Dennis Williamson
A: 
grep . file > file_op
Vijay Sarathi