sed '$!N;$!D' explanation
I know that
cat foo | sed '$!N;$!D'
will print out the last two lines of the fil开发者_C百科e foo, but I don't understand why.
I have read the man page and know that N joins the next line to the currently processed line etc - but could someone explain in 'good english' that matches the order of operation what is happening here, step by step?
thanks!
Here is what that script looks like when run through the sedsed
debugger (by Aurelio Jargas):
$ echo -e 'a\nb\nc\nd' | sed '$!N;$!D' PATT:^a$
PATT:^a$
COMM:$ !N
PATT:^a\Nb$
COMM:$ !D
PATT:^b$
COMM:$ !N
PATT:^b\Nc$
COMM:$ !D
PATT:^c$
COMM:$ !N
PATT:^c\Nd$
COMM:$ !D
PATT:^c\Nd$
c
d
I've filtered out the lines that would show hold space ("HOLD") since it's not being used. "PATT" shows what's in pattern space and "COMM" shoes the command about to be executed. "\N" indicates an embedded newline. Of course, "^" and "$" indicate the beginning and end of the string.
!N
appends the next line and !D
deletes the previous line and loops to the beginning of the script without doing an implicit print. When the last line is read, the $!
tests fail so there's nothing left to do and the script exits and performs an implicit print of what remains in the pattern space (since -n
was not specified in the arguments).
Disclaimer: I am a contributor to the sedsed
project and have made a few minor improvements including expanded color support, adding the ^
line-beginning indicator and preliminary support for Python 3. The bleeding edge version (which hasn't been touched lately) is here.
$!N;$!D
is a sed
program consisting of two statements, $!N
and $!D
.
$!N
matches everything but the last line of the last file of input ($
negated by !
) and runs the N
command on it, which as you said yourself appends the next line of input to the line currently under scrutiny (the "pattern space"). In other words, sed
now has two lines in the pattern space and has advanced to the next line.
$!D
also matches everything but the last line, and wipes the pattern space up to the first newline. D
also prevents sed
from wiping the entire pattern space when reading the next line.
So, the algorithm being executed is roughly:
For every line up to but not including the last {
Read the next line and append it to the pattern space
If still not at the last line
Delete the first line in the pattern space
}
Print the pattern space
精彩评论