首页 > 代码库 > Linux高级文本处理之sed(四)

Linux高级文本处理之sed(四)

模式空间是sed内部维护的一个缓存空间,它存放着读入的一行或者多行内容。但是模式空间的一个限制是无法保存模式空间中被处理的行,因此sed又引入了另外一个缓存空间——模式空间(Hold Space)。

一、保持空间

保持空间用于保存模式空间的内容,模式空间的内容可以复制到保持空间,同样地保持空间的内容可以复制回模式空间。sed提供了几组命令用来完成复制的工作,其它命令无法匹配也不能修改模式空间的内容。

操作保持空间的命令如下所示:

技术分享

这几组命令提供了保存、取回以及交换三个动作,交换命令比较容易理解,保存命令和取回命令都有大写和小写两种形式,这两种形式的区别是小写的是将会覆盖目的空间的内容,而大写的是将内容追加到目的空间,追加的内容和原有的内容是以\n分隔。

二、基本使用

实例1:h命令使用

[root@localhost ~]# cat text 
1
2
11
22
111
222

[root@localhost ~]# sed ‘h‘ text 
1
2
11
22
111
222

实例2:G命令使用

[root@localhost ~]# sed ‘G‘ text 
1

2

11

22

111

222

[root@localhost ~]#

说明:实例1返回结果正常,因为复制到保持空间的内容并没有取回;实例2每一行的后面都多了一个空行,原因是每行都会从保持空间取回一行,追加(大写的G)到模式空间的内容之后,以\n分隔。

实例3:使用x命令交换空间

[root@localhost ~]# sed ‘x‘ text 

1
2
11
22
111
  • 当读入第一行的时候,模式空间中的内容是第一行的内容,而保持空间是空的,这个时候交换两个空间,导致模式空间为空,保持空间为第一行的内容,因此输出为空行;

  • 当读入下一行之后,模式空间为第2行的内容,保持空间为第一行的内容,交换后输出第1行的内容;

  • 依次读入每一行,输出上一行的内容;

  • 直到最后一行被读入到模式空间,交换后输出倒数第二行的内容,而最后一行的内容并没有输出,此时命令执行结束。

高级命令执行过程图解:

技术分享

sedsed调试过程:

[root@localhost ~]# sedsed -d ‘H;g‘ num
PATT:a$
HOLD:$
COMM:H
PATT:a$
HOLD:\na$
COMM:g
PATT:\na$
HOLD:\na$
a
PATT:b$
HOLD:\na$
COMM:H
PATT:b$
HOLD:\na\nb$
COMM:g
PATT:\na\nb$
HOLD:\na\nb$
a
b
PATT:c$
HOLD:\na\nb$
COMM:H
PATT:c$
HOLD:\na\nb\nc$
COMM:g
PATT:\na\nb\nc$
HOLD:\na\nb\nc$
a
b
c


三、流程控制命令

为了使使用者在书写sed脚本的时候真正的"自由",sed还允许在脚本中用":"设置记号,然后用"b"和"t"命令进行流程控制。顾名思义,"b"表示"branch","t"表示"test";前者就是分支命令,后者则是测试命令。 首先来看标签的各式是什么。这个标签放置在你希望流程所开始的地方,单独放一行,以冒号开始。冒号与标签之间不允许有空格或者制表符,标签最后如果有空格的话,也会被认为是标签的一部分。 再来说b命令。它的格式是这样的:

[address]b[label]

它的含意是,如果满足address,则sed流程跟随标签跳转:如果标签指明的话,脚本首先假设这个标签在b命令以下的某行,然后转入该行执行相应的命令;如果这个标签不存在的话,控制流程就直接跳到脚本的末尾。否则继续执行后续的命令。 在某些情况下,b命令和!命令有些相似,但是!命令只能对紧挨它的{}中的内容起作用,而b命令则给予使用者足够的自由在sed脚本中选择哪些命令应该被执行,哪些命令不应该被执行。下面提供几种b命令的

经典用法:

(1) 创建循环:

:top
command1
command2
/pattern/b top
command3

(2) 忽略某些不满足条件的命令:

command1
/patern/b end
command2
:end
command3

(3) 命令的两个部分只能执行其中一个:

command1
/pattern/b dothere
command
b
:dothere
command3

t命令的格式和b命令是一样的:

[address]t[label]

它表示的是如果满足address的话,sed脚本就会根据t命令指示的标签进行流程转移。而标签的规则和上面讲的b命令的规则是一样的。下面也给出一个例子:

s/pattern/replacement/
t break
command
:break

四、sed实战

实例1:使用sed模拟出tac的功能(倒序输出)

[root@localhost ~]# cat num
1
2
3
4
5
[root@localhost ~]# sed ‘1!G;h;$!d‘ num
5
4
3
2
1

实例2:行列转换

[root@localhost ~]# cat num
    1
    2
    3
    4
    5

[root@localhost ~]# sed -ne ‘H;${x;s/\n/ /g;p}‘ num
 1 2 3 4 5

实例3:行列转换100之内数字求和

[root@localhost ~]# seq 100|sed -ne ‘H;${x;s/\n/+/g;s/^+//p}‘|bc
5050

实例4:追加匹配行到行尾

[root@localhost ~]# cat file
0
1 hello
2
3 hello
4
5
[root@localhost ~]# sed -e ‘/hello/{H;d}‘ -e ‘$G‘ file 
0
2
4
5

1 hello
3 hello

实例5:在文件中每行后面加空白行

[root@localhost ~]# cat num
1
2
3
4
5
[root@localhost ~]# sed ‘G‘ num
1

2

3

4

5

[root@localhost ~]#

实例6:保留文件最后一行

[root@localhost ~]# sed ‘$!d‘ num
5

实例7:保留文件的每一行后方有且只有一个空白行

[root@bash ~]# cat /etc/issue
\S
Kernel \r on an \m

Geek Young Learning Services
http://www.geekyoung.com

[root@bash ~]# sed ‘/^$/d;G‘ /etc/issue
\S

Kernel \r on an \m

Geek Young Learning Services

http://www.geekyoung.com

实例8:保留奇数行

[root@localhost ~]# cat num
1
2
3
4
5
[root@localhost ~]# sed ‘n;d‘ num
1
3
5

实例9:去基名

[root@localhost ~]# echo ‘/etc/sysconfig/network-scripts‘|sed -r ‘s@^.*/([^/]+)/?$@\1@‘
network-scripts

实例10:取目录名

[root@localhost ~]# echo ‘/etc/sysconfig/network-scripts/‘|sed -r ‘s@[^/]+/?$@@‘
/etc/sysconfig/

总结:sed高级用法灵活多变,使用前要搞清楚模式空间的内容,以及sed命令的执行过程,到此sed用法就结束了,要想灵活使用sed还得多练。


本文出自 “追求不完美” 博客,请务必保留此出处http://yolynn.blog.51cto.com/11575833/1890548

Linux高级文本处理之sed(四)