Why does this produce these results?
C:\>(echo a && echo b) | sed "1!G;h;$p"
a
b
a
b
a
C:\>
Added-
I see now there is no question, that it’d give those results.. but
(added note- 2nd line = last line. But I see you wrote last line to emphasise that it’s $ matching the 2nd line as last line. I accept that notation. Also, 1st line, 2nd line, last line, refer to lines of input.)
Jonathan, you wrote
a – 1st line, pattern space
b – 2nd line, pattern space, line 1
a – 2nd line, pattern space, line 2
b – last line, $p pattern space, line 1
a – last line, $p pattern space, line 2
But wouldn’t it be
Note- Dennis’s comment has confirmed that the “But wouldn’t it be” is correct
a – 1st line, pattern space
b – last line, $p pattern space, line 1
a – last line, $p pattern space, line 2
b – 2nd line, pattern space, line 1
a – 2nd line, pattern space, line 2
i.e. the same output
a
b
a
b
a
But the descriptions of how it did the b a, is the other way around
That’s assuming the $ operates on the last line, and not after it..
But what you wrote makes it look like the $ operates after it.
1!Gappends the hold space to the pattern space after the first line.hcopies the pattern space to the hold space (on every line).$pprints the last line (again).The first input line is ‘a’; the G command is ignored; the line is copied to the hold space; the line is printed (because you didn’t say
-n).The second input line is ‘b’; the G command appends the hold space (‘a’) to the pattern space (‘b’); the ‘h’ command copies the pattern space to the hold space; the pattern space is printed once because of the ‘no
-n‘.There is no more input, so the
$pacts and prints the pattern space.So, you get:
a– 1st line, pattern spaceb– 2nd line, pattern space, line 1a– 2nd line, pattern space, line 2b– last line, $p pattern space, line 1a– last line, $p pattern space, line 2The question is asked: did I tag the pairs of ‘b/a’ lines backwards?
Good question: not sure…how would we find out?
Let’s add another operation to the ‘$’ set:
The output is:
which shows that the
$pprint does occur before the$s///operation, which occurs before the final print of the pattern space.One side-effect of this observation, which caught me by surprise (but makes sense on reflection), is that
sedknows when it is processing the last line as it is running the script on the last line. That means it does read-ahead after the newline to see whether there is more data to fetch. Dennis Williamson shows that the sed source at about line 928 contains a functiontest_eof()which does indeed do one character of lookahead.(One of the good things about SO is that you learn even as you teach!)
So, somewhat to my surprise, it seems thatsedknows when it has reached the last line before it processes it – so it seems to do some sort of read-ahead. Either that or I’ve misunderstood something really badly, or it’s too late and I need to go to sleep.