sed '$!N;/^\[second/,/^\n\[/P;D' <infile >outfile
That should probably do, though I'm not perfectly clear about what you want to do with the trailing blank line that immediately precedes the next section. This output includes it, because it seems the right thing to do, but if you want to drop only that one last blank line from any section that can be done relatively easily - so just ask.
Basically, for every input line which is
! not the
sed also pulls in the
Next line and appends it to pattern space following an inserted
\newline character delimiter. Each time this happens the pattern space shifts:
If the current pattern space matches the patterns
^\n\[ or any line which occurs between those two,
Print up to the first occurring
\newline in pattern space - and so it only prints half of its buffer for each iteration.
Deletes up to the first occurring
\newline in pattern space and starts the script again from the top - which is how we get the shifting effect. This is known as a sliding window. It works very well, and is quite fast.
I guess there are multiple versions of this question or something? Whatever the case, going the opposite way is not so difficult to do, really.
You might do it like...
sed -ne '/^\[[^s]/,/^\[s/p' <in >out
Which would just print any content which doesn't follow a header beginning with an
s character, and and all headers regardless. It doesn't do the neat little newline after, though:
[third attempt ]
If you want to get a little more explicit you can do that too:
sed '/^\[[second]/P;$!N;//,/\n$/!P;D' <in >out
...which does do the neat little newline...
[third attempt ]
All of these are
sed ranges, and for each match expression that looks like:
sed will apply the
command to both matched lines and all lines that come between.