sed normally processes the file one line at a time, but if you add newlines (or use certain
sed commands that read/add content to the "pattern space"), it can contain multiple lines at the same time. In particular when your
sed script processes the line "
bb", it first replaces it with "
\nff" (where the
\n represents an actual newline), then compares the entire pattern space with the regex
^$, finds that it doesn't match, and ignores that command. (Note: in this context,
$ don't refer to the beginning and end of the line, the refer to the beginning and end of the pattern space).
Solution: if I understand your goal correctly, the second test should check for the pattern space starting with a newline (
^\n) and if so delete the newline (not the entire pattern space). You can do this with the substitution
Essentially, this will add a line break if the "bb" pattern was at the beginning of a line, but not if it's later in the line:
$ printf '%s\n' aa bb cc dd prefixbbsuffix | sed 's/bb/\nff/g;s/^\n//'
Alternately, you could run two separate
sed commands, so the second one re-breals lines treating the added line as a separate item:
printf '%s\n' aa bb cc dd prefixbbsuffix | sed 's/bb/\nff/g' | sed '/^$/d'
If that's not your actual goal, please edit your question to clarify it.