With sed the easiest way would be to first read the whole file into the pattern space and work on that:
sed ':a $!{N; ba}; s/\(^\|\n\)---\n/\n/2' filename
This does
:a # jump label for looping
$!{ # if the end of input is not reached
N # fetch the next line, append it to the pattern space
ba # go back to :a
} # after this, the whole file is in the pattern space.
s/\(^\|\n\)---\n/\n/2 # then: remove the second occurrence of a line that
# consists only of ---
@mklement0 points out that the \|
only works with GNU sed. A way to work around that, since the \|
is only necessary to catch ---
in the first line, would be
sed ':a $!{ N; ba; }; s/^/\n/; s/\n---\n/\n/2; s/^\n//' filename
This does:
:a $!{ N; ba; } # read file into the pattern space
s/^/\n/ # insert a newline before the first line
s/\n---\n/\n/2 # replace the second occurrence of \n---\n with \n
s/\n// # remove the newline we put in at the beginning.
This way, the first line is no longer a special case.
Without reading the whole file into a buffer, you'll have to construct a counter from characters:
sed '/^---$/ { x; s/.*/&_/; /^__$/ { x; d; }; x; }' filename
That is:
/^---$/ { # if a line is ---
x # exchange pattern space and hold buffer
s/.*/&_/ # append a _ to what was the hold buffer
/^__$/ { # if there are exactly two in them
x # swap back
d # delete the line
}
x # otherwise just swap back.
}
...or just use awk:
awk '!/^---$/ || ++ctr != 2' filename