模式空间是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
原文地址:http://yolynn.blog.51cto.com/11575833/1890548