sed高级用法
sed有模式空间和保持空间,保持空间在默认情况下是不会被使用到的,只有在某些命令下才会被使用。
(1)模式空间:进行文本处理。
(2)保持空间:把数据临时存放在这里。
-
g:将保持空间的内容拷贝到模式空间中,原模式空间将被清零。
-
G:将保持空间的内容追加到模式空间\n之后。
-
h:将模式空间的内容拷贝到保持空间中,原保持空间将被清零。
-
H:将模式空间的内容追加到保持空间\n之后。
-
d:删除模式空间中的所有行,并读入下一行。
-
D:删除模式空间的第一行,不读入下一行。
-
x:交换内容
-
n:读取下一行到模式空间。
-
N:将下一行追加到模式空间后
1.N
N 命令会将下一行文本内容添加到缓冲区已有数据之后(之间用换行符分隔),从而使前后两个文本行同时位于缓冲区中,sed 命令会将这两行数据当成一行来处理。
[root@localhost ~]# cat test
wo shi cai ao cheng ta die
xx
zz
sb
chenshunli
[root@localhost ~]# sed '/sb/N;s/\n//' test
wo shi cai ao cheng ta die
xx
zz
sbchenshunli
//在这个例子中,sed 命令查找含有单词 sb 的那行文本。找到该行后,它会用 N 命令将下一行合并到那行,然后用替换命令 s 将换行符替换成空。结果是,文本文件中的两行在 sed 的输出中成了一行。
[root@localhost ~]# cat test
On Tuesday, the Linux System
Administrator's group meeting will be held.
[root@localhost ~]# sed 'N;s/System\nAdministrator/Desktop User/' test
On Tuesday, the Linux Desktop User's group meeting will be held
//查找单行中短语的替换命令在数据流的后一行也能正常工作,多行替换命令则会负责短语出现在数据流中间的情
2.D
D 多行删除命令
sed 不仅提供了单行删除命令(d),也提供了多行删除命令 D,其作用是只删除缓冲区中的第一行,也就是说,D 命令将缓冲区中第一个换行符(包括换行符)之前的内容删除掉。
[root@localhost ~]# cat test
On Tuesday, the Linux System
Administrator's group meeting will be held
All System Administrators should attend.
[root@localhost ~]# sed 'N;/System\nAdministrator/D' test
Administrator's group meeting will be held
All System Administrators should attend.
//文本的第二行被 N 命令加到了缓冲区,因此 sed 命令第一次匹配就是成功,而 D 命令会将缓冲区中第一个换行符之前(也就是第一行)的数据删除,所以,得到了如上所示的结果
[root@localhost ~]# cat data
sbxk
sbcac
erzicac
sbcsl
[root@localhost ~]# sed '/^$/{N; /sbxk/D}' data
sbxk
sbcac
erzicac
sbcsl
//sed会查找空白行,然后用 N 命令来将下一文本行添加到缓冲区。此时如果缓冲区的内容中含有单词 sbxk,则 D 命令会删除缓冲区中的第一行。
[root@localhost ~]# sed '
/^$/{
N;/sb/D
N;/csl/D
}' data
sbxk
sbcac
erzicac
sbcsl
3.h和g,G
通常,在使用 h 或 H 命令将字符串移动到保持空间后,最终还要用 g、G 或 x 命令将保存的字符串移回模式空间。保持空间最直接的作用是,一旦我们将模式空间中所有的文件复制到保持空间中,就可以清空模式空间来加载其他要处理的文本内容
Hold命令用模式空间的内容取代保持空间的内容。
[root@localhost ~]# cat data
hello the world
hello minger
golang
python
linux
[root@localhost ~]# sed '2h;5G' data
hello the world
hello minger
golang
python
linux
hello minger
[root@localhost ~]# sed '2h;5g' data
hello the world
hello minger
golang
python
hello minger
[root@localhost ~]# cat data
A
a
B
b
C
c
D
d
[root@localhost ~]# sed -n 'h;n;p;g;p' data
a
A
b
B
c
C
d
D
4.H和g,G
将模式空间的内容追加到保持空间Hole命令在保持空间的内容之后放置一个换行符,且后面跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。
[root@localhost ~]# cat data
hello the world
hello minger
golang
python
linux
[root@localhost ~]# sed '2H;5g' data
hello the world
hello minger
golang
python
hello minger
[root@localhost ~]# sed '2H;5G' data
hello the world
hello minger
golang
python
linux
hello minger
[root@localhost ~]# cat test
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed -n '/first/{h;p;n;p;g;p}' test
This is the first data line.
This is the second data line.
This is the first data line.
这个例子的运行过程是这样的:
sed脚本命令用正则表达式过滤出含有单词first的行;
当含有单词 first 的行出现时,h 命令将该行放到保持空间;
p 命令打印模式空间也就是第一个数据行的内容;
n 命令提取数据流中的下一行(This is the second data line),并将它放到模式空间;
p 命令打印模式空间的内容,现在是第二个数据行;
g 命令将保持空间的内容(This is the first data line)放回模式空间,替换当前文本;
p 命令打印模式空间的当前内容,现在变回第一个数据行了。
5.x
交换内容
[root@localhost ~]# cat test2
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed '/header/h;/first/x' test2
This is the header line.
This is the header line.
This is the second data line.
This is the last line.
h 将匹配到的name 行 ,添加至保持空间
x 将保持空间的内容和模式空间互换
6.b
b 分支命令
通常,sed 程序的执行过程会从第一个脚本命令开始,一直执行到最后一个脚本命令(D 命令是个例外,它会强制 sed 返回到脚本的顶部,而不读取新的行)。sed 提供了 b 分支命令来改变命令脚本的执行流程,其结果与结构化编程类似。
b 分支命令基本格式为:
[address]b [label]
其中,address 参数决定了哪些行的数据会触发分支命令,label 参数定义了要跳转到的位置。
需要注意的是,如果没有加 label 参数,跳转命令会跳转到脚本的结尾,比如
[root@localhost ~]# cat test2
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed '2,3b;s/This is/Ls this/;s/line./test?/' test2
Ls this the header test?
This is the first data line.
This is the second data line.
Ls this the last test?
//可以看到,因为 b 命令未指定 label 参数,因此数据流中的第2行和第3行并没有执行那两个替换命令。
//如果我们不想直接跳到脚本的结尾,可以为 b 命令指定一个标签(也就是格式中的 label,最多为 7 个字符长度)。在使用此该标签时,要以冒号开始(比如 :label2),并将其放到要跳过的脚本命令之后。这样,当 sed 命令匹配并处理该行文本时,会跳过标签之前所有的脚本命令,但会执行标签之后的脚本命令。
[root@localhost ~]# sed '{/first/b jump1;s/This is the/No jump on/
:jump1
s/This is the/Jumpe here on/}' test2
No jump on header line.
Jumpe here on first data line.
No jump on second data line.
No jump on last line.