tags:

views:

204

answers:

4

I define a 'block' of text as all lines between start of file, newline or end of file:

block1
block2
block3

anotherblock4
anotherblock5
anotherblock6

lastblock7
lastblock8

Any text can occupy a block - it is unknown what lines are there. I tried to write a shell script to insert a new line at the 2nd block, but since sed doesn't like working with newlines, I hacked around this sed oneliner:

sed -n "H;\${g;s/\n\n/\nTEST\n\n/2;p}"

This results into:

[newline]
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6
TEST

lastblock7
lastblock8

The problem is, it adds a newline to the start of the buffer (marked as [newline] because StackOverflow's markup cannot show it) Is there another way to do it using a different tool or different regexp?

A: 

OK, this isn't my proudest moment, but I think it does what you want... Maybe? I wasn't able to get sed to do anything useful as, at least on my machine, it doesn't like working with newlines in an s/x/y substitution command.

# cat blocks
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6

lastblock7
lastblock8
# python -c 'import sys,re; print re.sub("(\n\n[\s\S]*?\n)(\n)", "\\1TEST\n\\2", sys.stdin.read(), 1),' < blocks
block1
block2
block3

anotherblock4
anotherblock5
anotherblock6
TEST

lastblock7
lastblock8

Notes:

  • There's no equivalent of sed's "replace the 2nd match" option, so I needed a more complicated regex.
  • . doesn't match newlines, thus [\s\S].
  • The ? makes the * non-greedy.
  • The 4th parameter of 1 limits this to a single replacement.
  • The comma at the end inhibits print from adding an extra newline.


Alternatively, you could tack "| tail +2" on after the almost-but-not-quite-right sed command to chop off the first line of output.

John Kugelman
You mean '| tail -c +2'? That is my current workaround. I'm looking into educating myself better into sed and bash in general.
LiraNuna
+1  A: 

here's one possible solution

awk '/^$/{f++}f==2{print "TEST\n";f=0;next}1' file
ghostdog74
ok.its fixed to get rid of last newline
ghostdog74
+2  A: 

This does what you want and gets rid of the unwanted newline at the beginning:

sed -n "1{x;d};H;\${g;s/\n\n/\nTEST\n\n/2;p}"
Dennis Williamson
A: 

One more awk solution. This asks awk to keep track of paragraphs instead of counting them yourself like ghostdog74's solution.

awk -v 'RS=\n\n' '{print}NR==2{print"TEST"}{print""}'
ephemient
this solution was presented as well, but it will add a newline at the last block and someone(i think its the author) commented on that.
ghostdog74