Raw Input Desired Output
Paragraph 1
Paragraph 1
Paragraph 1


Paragraph 2
Paragraph 2

Paragraph 3
--para begin--
Paragraph 1
Paragraph 1
Paragraph 1
--para ends--


--para begin--
Paragraph 2
Paragraph 2
--para ends--

--para begin--
Paragraph 3
--para ends--
Script and Comments
Script1
[ 1] /^$/b
[ 2] i\
[ 3] --para begin--
[ 4] :loop
[ 5] $!{
[ 6] N
[ 7] /\n$/!{
[ 8] P;s/.*\n//
[ 9] b loop
[10] }
[11] }
[12] s/[^\n]*/&\n--para ends--/
Comments
  1. Adjacent paragraphs are separated by one or more blank lines.
  2. This script will keep at most 2 lines in the pattern space.
  3. Flowchart:
    flowchart
  4. When sed meets a blank line (except the first one following the end of a paragraph), since no label is specified, command 'b' will make sed jump to the end of the script.
  5. After reading the first line of each paragraph, sed will execute step [2,3], where we use command 'i' to insert a header.
  6. Then the loop consisting of steps [4] thru [9] will repeat
    • appending next line
    • print and remove the previous line
    until the end of a paragraph is reached.
  7. When the newly appended line is either
    • a blank line,
      in this case, '/\n$/ matches.
    • or the last line of the file
    we know that the end of a paragraph is reached, and use step [12] to add the ending line.