Subject: bug#49590: Error in GNU sed manual

From: Davide Brini <[email-masked]>
Date: Fri, 16 Jul 2021 16:12:34 +0200

On Fri, 16 Jul 2021 00:45:07 +0000, Matthew Hoffman via <[email-masked]>
wrote:

> Dear GNU people:
>
> The GNU sed manual seems to have an error in it.
>
> In this section:
>
> 6.3 Multiline techniques - using D,G,H,N,P to
> process multiple lines
>
> You have this example code:
>
> sed '/./{H;$!d} ; x ; s/^/\nSTART-->/ ; s/$/\n<--END/' input.txt
>
> The input file you give is:
>
> a a a aa aaa
> aaaa aaaa aa
> aaaa aaa aaa
> bbbb bbb bbb
> bb bb bbb bb
> bbbbbbbb bbb
> ccc ccc cccc
> cccc ccccc c
> cc cc cc cc

Not really. The input file is:

--- start here -----
a a a aa aaa
aaaa aaaa aa
aaaa aaa aaa

bbbb bbb bbb
bb bb bbb bb
bbbbbbbb bbb

ccc ccc cccc
cccc ccccc c
cc cc cc cc

--- end here ----

empty lines are important.

> and the output promised is:
>
> START-->
> a a a aa aaa
> aaaa aaaa aa
> aaaa aaa aaa
> <--END
> START-->
> bbbb bbb bbb
> bb bb bbb bb
> bbbbbbbb bbb
> <--END
> START-->
> ccc ccc cccc
> cccc ccccc c
> cc cc cc cc
> <--END

Again, you missed the empty lines.

> This seemed wrong to me, because as I understood it the '$' symbol should
> indicate the last line of the file, not merely a blank line, so I
> executed it on my GNU sed 4.7, and this is the output you get:
>
> START-->
> a a a aa aaa
> aaaa aaaa aa
> aaaa aaa aaa
> bbbb bbb bbb
> bb bb bbb bb
> bbbbbbbb bbb
> ccc ccc cccc
> cccc ccccc c
> cc cc cc cc
> <--END

With the (incorrect) input file you showed, yes, this is what you get.
With the actual file, you get the output shown in the manual.

BTW, in this case the dollar sign ($) is not representing the last line of
the file, but the end of a buffer. Here's a brief explanation of what the
code does:

/./{H;$!d}
This loads a full "paragraph" (ie lines that come before an empty line)
into the hold buffer. Remember that "d" starts a new cycle.

x
This inverts the pattern and the hold buffer, so the paragraph is in the
pattern buffer.

s/^/\nSTART-->/ ; s/$/\n<--END/
This merely prepends '\nSTART-->' and appends '\n<--END' to a paragraph
(with literal newlines). Here, ^ represent the beginning of the buffer, and
$ the end of the buffer.

Finally, since by default sed prints the contents of the pattern buffer at
the end of a cycle, the decorated paragraph is then printed.

--
D.