sed高级用法(GHDNPD)

##How does the command sed ‘1!G;h;$!d’ reverse the contents of a file?
参考:
https://unix.stackexchange.com/questions/233014/how-does-the-command-sed-1ghd-reverse-the-contents-of-a-file
http://blog.csdn.net/itsenlin/article/details/21129405

1
2
3
4
5
6
7
8
9
#test.txt

1
2
3
4
5
6
7
1
sed '1!G;h;$!d' test.txt
1
2
3
4
d     	Delete pattern space.  Start next cycle.    删除pattern space的内容,开始下一个循环.
h、 H Copy/append pattern space to hold space. 复制/追加pattern space的内容到hold space.
g、 G Copy/append hold space to pattern space. 复制/追加hold space的内容到pattern space.
x Exchange the contents of the hold and pattern spaces. 交换hold space和pattern space的内容.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sed'1!G; h; $!d' 文件
首先,sed拥有一个占有空间和一个模式空间。在专注于特定的命令之前,我们必须区分它们。

当sed读取新行时,它被加载到模式空间中。因此,每次处理新行时都会覆盖该空间。另一方面,在整个处理过程中保持空间是一致的,并且值可以存储在那里供以后使用。

以下命令:

在这个语句中有3个命令:1!G,h和$!d

1!G意味着该G命令在除第一行之外的每一行执行(!否定1)。G意味着将保存空间中的内容追加到模式空间中。

h适用于每一行。它将模式空间复制到保留空间(并覆盖它)。

$!d适用于除最后一行之外的每一行($表示最后一行,!否定它)。d是删除行(模式空间)的命令。

现在,读取第一行时,sed执行该h命令。第一行被复制到保存空间中。然后它被删除,因为它符合$!条件。sed继续第二行。
第二行符合条件1!(不是第一行),因此保留空间(具有第一行)被附加到模式空间(具有第二行)。之后,在模式空间中,现在是第二行,后面跟着第一行,由换行符分隔。现在,该h命令适用(如在每行中); 模式空间中的所有内容都被复制到保存空间。第三条语句($!d)适用:该行将从模式空间中删除。
第2步现在完成所有行。我们跳到最后一行。
在最后一行($)中,几乎全部步骤2完成,但不是删除部分(d)。sed,如果没有调用-n,则在每个输入行的处理结束时自动打印模式空间。所以,不删除时,模式空间打印。它现在包含所有倒行顺序的行。

sed’1!G; h; $!d’ 文件

1!G : 第一行不从保持空间中拿数据, 因为是空的
h: 模式空间的数据 拷贝到 保持空间 , 是覆盖操作
$!d: 不是最后一行就删除模式空间的内容, 因为读完一行 模式空间有内容sed就会输出

第一行操作 : 模式空间读入行数据, 1!G(满足);不从保持空间拿数据, h(满足) 模式空间内容拷贝到保持空间, $!d(满足)删除模式空间的内容 | 模式空间没数据 sed就不打印

第二行操作 : 模式空间读入行数据, 1!G(不满足,所以执行G);从保持空间拿数据(变成第二行\n第一行), h(满足) 模式空间内容拷贝到保持空间, $!d(满足)删除模式空间的内容 | 模式空间没数据 sed就不打印

第三行操作 : 模式空间读入行数据, 1!G(不满足,所以执行G);从保持空间拿数据(变成第三行\n第二行\n第一行), h(满足) 模式空间内容拷贝到保持空间, $!d(满足)删除模式空间的内容 | 模式空间没数据 sed就不打印

最后一行操作: 模式空间读入行数据, 1!G(不满足,所以执行G);从保持空间拿数据(变成最后一行\n…第三行\n第二行\n第一行), h(满足) 模式空间内容拷贝到保持空间, $!d(最后一行就不执行d)保留模式空间的内容 | 模式空间有数据 sed打印模式空间的数据

NPD命令

参考:
http://blog.csdn.net/heihuifeng/article/details/7943982

1
2
3
4
5
6
7
8
9
10
11
再贴上N P D的解释:

P:Print up to the first embedded newline of the current pattern space.
(就是输出模式空间开头到第一个\n之间的内容)

D:If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.
(是删除模式空间开头到第一个\n(含)之间的内容,并且控制流跳到脚本的第一条语句。这里一定要注意这句话“and restart cycle with the resultant pattern space, without reading a new line of input.”,即它是在不改变当前行号的情况下,从头执行的。)
这句话也充分的说明了,为什么很多人不愿意读中文翻译版书籍的原因。:-)

N:Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then sed exits without processing any more commands.
(追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。如果没有下一个可处理的行,则退出)
1
2
3
4
5
6
7
8
d  删除资料。
D 删除 pattern space 内第一个 newline 字母 / 前的资料。

n 读入下一笔资料。
N 添加下一笔资料到 pattern space。

p 印出资料。
P 印出 pattern space 内第一个 newline 字母 / 前的资料。
1
2
3
4
5
test.txt
#
1
2
3
1
sed -E -ne '/#/!p'  test.txt

打印:
1
2
3

1
2
# 在mac os ; -r 和 mac里的-E 一样 , mac中没有-r
sed -E -e :a -e '$!N;/#/!s/\n//;ta' -e 'P;D' test.txt
1
2
# 在Linux ; -r 和 mac里的-E 一样 , mac中没有-r
sed -r ':a;$!N;/#/!s/\n/ /;ta;P;D' urfile

-n 的作用

By default, each line of input is echoed to the standard output
after all of the commands have been applied to it. The -n option
suppresses this behavior.

默认情况下,每一行输入都回显到标准输出。
在所有的命令都被应用到它之后。-n选项
抑制这种行为。

默认情况加 每一行都打印 只要模式空间中有数据 都打印,
-n的作用是 取消这种行为, -n和p命令结合 选择性的打印…

sed 打印行号

1
sed -ne '{=;p;}' web.xml | sed -E -e '$!N;s/\n/	/'