分类: LINUX
2010-11-22 18:40:40
Sed高级用法
1. Sed脚本的处理过程:
Sed有一个模式空间这个名词,sed默认是一行一行的将文件读入到模式空间里的,然后对模式空间里的内容进行命令和匹配操作;
默认的从模式空间出来的内容是打印到屏幕上的,但用-n和-quiet可以屏蔽这个功能。
举例说明:
Sed -n '/alibaba/,/fuck/{w tao.txt;/girl/i\hello,MM;d} tao
1) 首先将匹配地址地位到/alibaba/,/fuck/,如果没有/fuck/则匹配到文件尾;
2)然后按行读入第一行/alibaba/到模式空间里,然后依照顺序执行脚本里的命令。
3)再依次往下读,一行一行的读入到模式空间了,进行处理。
4)处理结果是,在tao.txt中写入了从/alibaba/到/fuck/的行,如果有匹配girl的会打印出hell,MM;其他的一概不打印。
2. 多行模式里三个命令N,D,P
多行处理的命令常用的就这三个,估计就这三个,如果还有请留言,同学习。
N:类似n,只不过-n在处理的时候是用下一行来替换模式空间里的内容;而-N是将下一行追加到模式空间里面。
D:类似d,-d删除的是模式空间里的所有内容,而D删除的是模式空间里的第一行,即当用N命令读入下一行进入模式空间的时候用D命令只会删除第一行。
P:类似p,从上诉的介绍应该可以猜测出P的作用了,对,就是打印模式空间的第一行内容。
举例说明下:
root@localhost:~/test#sed -n '/it/{N;p}' tao
it is john ,bigjohn!
alibaba
root@localhost:~/test#sed -n '/it/{N;P}' tao
it is john ,bigjohn!
root@localhost:~/test#sed '/it/{N;s/john!\nalibaba/good alibaba\ndd/;}' tao
it is john ,biggood alibaba
dd
从书上看到一个用N,D,P建立一个输入/输出循环的例子:
Sed ' /Unix/{
N
s/\nSystem/Operating &/
P
D
}' exp5
#Cat exp5
Here are examples of the UNIX
System. Where UNIX
System appears, it should be the UNIX
Operating System.
脚本执行后:
root@localhost:~/test#sed '/UNIX/{
N
s/\nSystem/ Operating &/
P
D
}' exp5
Here are examples of the UNIX Operating
System. Where UNIX Operating
System appears, it should be the UNIX
Operating System.
解释:这个脚本用于维护两行的模式空间,但一次只输出一行。这个循环的目的是输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。
网上看到这样一个例子,挺能说明问题的:
$ cat expl.6
I want to see @fl(what will happen) if we put the
font change commands @fl(on a set of lines). If I understand
things (correctly), the @fl(third) line causes problems. (No?).
Is this really the case, or is it (maybe) just something else?
Let's test having two on a line @fl(here) and @fl(there) as
well as one that begins on one line and ends @fl(somewhere
on another line). What if @fl(it is here) on the line?
Another @fl(one).
现在要作的就是将"fl@(…)替换为"\fB(…)\fR。以下就是满足条件的sed 命令:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> P
> D
> }' expl.6
然而,如果不使用这种输入输出循环,而是单单用N 来实现的话,就会出现问题:
$ sed 's/@fl(\([^)]*\))/\\fB\1\\fR/g
> /@fl(.*/{
> N
> s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g
> }' expl.6
这样的sed 脚本是有漏洞的。
解释:其实这个很简单啦,第二个错误的是因为,在N之后加入的行,没有进行脚本命 令从头开始的处理。
3.:,b,t的用法
这个借鉴网上的一个很好的说明:
为了使使用者在书写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
还是用例6 的sed 脚本为例子。其实仔细思考一下就会发现这个脚本不是足够强大:如果某
个@fl 结构跨越了两行,比如说三行怎么办?这就需要下面这个加强 版的sed 了:
$ cat expl.6.sed
:begin
/@fl(\([^)]*\))/{
s//\\fB\1\\fR/g
b begin
}
/@fl(.*/{
N
s/@f1(\([^)]*\n[^)]*\))/\\fB\1\\fR/g
t again
b begin
}
:again
P
D
4.H,h,g,G,y这个在基本用法中已做介绍了,举个例子吧:
root@localhost:~/test#cat tao
alibaba ff
alibaba
this is a test file
-tao shou kun has a english na
it is john ,bigjohn!
alibaba
companytao
Now
root@localhost:~/test#sed '
/ff/{
h
d
}
/alibaba/{
G
}
' tao
处理后就是将第一行复制到/alibaba/匹配的行后面。用g的话是在/alibaba/匹配的行上进行替换。
chinaunix网友2010-11-23 14:44:58
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com