sed的大师级用法.docx
- 文档编号:9038816
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:17
- 大小:32.18KB
sed的大师级用法.docx
《sed的大师级用法.docx》由会员分享,可在线阅读,更多相关《sed的大师级用法.docx(17页珍藏版)》请在冰点文库上搜索。
sed的大师级用法
LUPA论坛»技术文档区(只读/存档)»Shell编程»sed的大师级用法
‹‹上一主题|下一主题››
∙发新话题
∙发布投票
∙发布商品
∙发布悬赏
∙发布活动
∙发布辩论
∙发布视频
窗体顶端
打印
sed的大师级用法
1#发表于2007-3-3000:
21
sed的大师级用法
在论坛上见了置顶的帖子,其中有个是关于sed的,看了但是不完全。
另外我根据O'Reilly图书的电子版本的《sed&awk》学习了这个命令,就接合自己的使用经验大致翻译了这本图书中有关sed的高级用法的部分。
当然,这本书有买的,不过很少了,而且贵。
希望我做的这个工作能够帮助坛子里像我这样的穷人。
如果有错误,大家不要用砖砸我,给我指出来就好了。
由于最近忙一个化工流程的设计,所以我只有慢慢做这个事情。
我会一部分一部分地把这个工作做下去的。
也许也后有时间的话,把awk的高级用法也作了。
在此希望版主顶一下,大家也不要回。
我这一辈子都不可能用编写软件的方式参与开源事业了,希望能够通过这种方式从旁边推一把。
书的原文可以在这个地方找到:
http:
//www.unix.org.ua/orelly/
首先,应该明白模式空间的定义。
模式空间就是读入行所在的缓存,sed对文本行进行的处理都是在这个缓存中进行的。
这对接下来的学习是有帮助的。
在正常情况下,sed将待处理的行读入模式空间,脚本中的命令就一条接着一条的对该行进行处理,直到脚本执行完毕,然后该行被输出,模式空间请空;然后重复刚才的动作,文件中的新的一行被读入,直到文件处理完备。
但是,各种各样的原因,比如用户希望在某个条件下脚本中的某个命令被执行,或者希望模式空间得到保留以便下一次的处理,都有可能使得sed在处理文件的时候不按照正常的流程来进行。
这个时候,sed设置了一些高级命令来满足用户的要求。
总的来说,这些命令可以划分为以下三类:
1.N、D、P:
处理多行模式空间的问题;
2.H、h、G、g、x:
将模式空间的内容放入存储空间以便接下来的编辑;
3.:
、b、t:
在脚本中实现分支与条件结构。
多行模式空间的处理:
由于正则表达式是面向行的,因此,如若某个词组一不分位于某行的结尾,另外一部分又在下一行的开始,这个时候用grep等命令来处理就相当的困难。
然而,借助于sed的多行命令N、D、P,却可以轻易地完成这个任务。
多行Next(N)命令是相对于next(n)命令的,后者将模式空间中的内容输出,然后把下一行读入模式空间,但是脚本并不会转移到开始而是从当前的n命令之后开始执行;而前者则保存原来模式空间中的内容,再把新的一行读入,两者之间依靠一个换行符"\n"来分隔。
在N命令执行后,控制流将继续用N命令以后的命令对模式空间进行处理。
值得注意的是,在多行模式中,特殊字符"^"和"$"匹配的是模式空间的最开始与最末尾,而不是内嵌"\n"的开始与末尾。
例1:
$catexpl.1
ConsultSection3.1intheOwnerandOperator
Guideforadescriptionofthetapedrives
availableonyoursystem.
现在要将"OwnerandOperatorGuide"替换为"InstallationGuide":
$sed'/Operator$/{
>N
>s/OwnerandOperator\nGuide/InstallationGuide\
>/
>}'expl.1
在上面的例子中要注意的是,行与行之间存在内嵌的换行符;另外在用于替代的内容中要插入换行符的话,要用如上的"\"的转义。
再看一个例子:
例2:
$catexpl.2
ConsultSection3.1intheOwnerandOperator
Guideforadescriptionofthetapedrives
availableonyoursystem.
LookintheOwnerandOperatorGuideshippedwithyoursystem.
TwomanualsareprovidedincludingtheOwnerand
OperatorGuideandtheUserGuide.
TheOwnerandOperatorGuideisshippedwithyoursystem.
$sed's/OwnerandOperatorGuide/InstallationGuide/
>/Owner/{
>N
>s/*\n//
>s/OwnerandOperatorGuide*/InstallationGuide\
>/
}'expl.2
结果得到:
ConsultSection3.1intheInstallationGuide
foradescriptionofthetapedrives
availableonyoursystem.
LookintheInstallationGuideshippedwithyoursystem.
TwomanualsareprovidedincludingtheInstallationGuide
andtheUserGuide.
TheInstallationGuideisshippedwithyoursystem.
看上去sed命令中作了两次替换是多余的。
实际上,如果去掉第一次替换,再运行脚本,就会发现输出存在两个问题。
一个是结果中最后一行不会被替换(在某些版本的sed中甚至不会被输出)。
这是因为最后一行匹配了"Owner",执行N命令,但是已经到了文件末尾,某些版本就会直接打印这行再退出,而另外一些版本则是不作出打印立即退出。
对于这个问题可以通过命令"$!
N"来解决。
这表示N命令对最后一行不起作用。
另外一个问题是"lookmanuals"一段被拆为两行,而且与下一段的空行被删除了。
这是因为内嵌的换行符被替换的结果。
因此,sed中做两次替换一点也不是多余的。
例3:
$catexpl.3
ThisisatestparagraphinInterleafstyleASCII.Anotherline
inaparagraph.Yetanother.
v.1111111111111111111111100000000000000000001111111111111000000
100001000100100010001000001000000000000000000000000000000000000
000000
Morelinesoftexttobefoundafterthefigure.
Theselinesshouldprint.
我们的sed命令是这样的:
$sed'/
>N
>c\
>.LP
>}
>/
>wfig.interleaf
>/
>.FG\
>
>.FE
>d
>}
>/^$/d'expl.3
运行后得到的结果是:
.LP
ThisisatestparagraphinInterleafstyleASCII.Anotherline
inaparagraph.Yetanother.
.FG
.FE
.LP
Morelinesoftexttoefoundafterthefigure.
Theselinesshouldprint.
而
值得注意的是命令"d"并不会影响命令i插入的内容。
命令"d"作用是删除模式空间的内容,然后读入新的行,sed脚本从头再次开始执行。
而命令"D"的不同之处在于它删除的是直到第一个内嵌换行符为止的模式空间的一部分,但是不会读入新的行,脚本将回到开始对剩下内容进行处理。
例4:
$catexpl.4
Thislineisfollowedby1blankline.
Thislineisfollowedby2blankline.
Thislineisfollowedby3blankline.
Thislineisfollowedby4blankline.
Thisistheend.
不同的删除命令获得不同的结果:
$sed'/^$/{$sed'/^$/{
>N>N
>/^\n$/d>/^\n$/D
>}'expl.4>}'expl.4
sed对文件中每一行(不管处理与否)的默认动作是将其输出,如果加上选项"-n",则输出动作会被抑制,这时还希望输出就需要打印命令。
单行模式空间的打印命令是"p",多行模式空间的打印命令是"P"。
P命令打印的是模式空间中直到第一个内嵌换行符为止的一部分。
P命令通常出现在N命令之后D命令之前,由此构成一个输入输出循环。
在这种情况下,模式空间中始终存在两行文本,而输出始终是一行文本。
使用这种循环的目的在于输出模式空间中的第一行,然后脚本回到起始处,再对空间中的第二行进行处理。
设想一下,如果没有这个循环,当脚本执行完备,模式空间中的内容都会被输出,可能就不符合使用者的要求或者降低了程序执行的效率。
下面是一个例子:
例5:
$catexpl.5
HereareexamplesoftheUNIX
System.WhereUNIX
Systemappears,itshouldbetheUNIX
OperatingSystem.
$sed'/UNIX$/{
>N
>/\nSystem/{
>s//Operating&/
>P
>D
>}
>}'expl.5
替换的结果是:
HereareexamplesoftheUNIXOperating
System.WhereUNIXOperating
Systemappears,itshouldbetheUNIX
OperatingSystem.
可以将sed命令中的"P"、"D"换作小写,比较一下两种类型的命令的不同之处。
下面的例子就有相当的难度了:
例6:
$catexpl.6
Iwanttosee@fl(whatwillhappen)ifweputthe
fontchangecommands@fl(onasetoflines).IfIunderstand
things(correctly),the@fl(third)linecausesproblems.(No?
).
Isthisreallythecase,orisit(maybe)justsomethingelse?
Let'stesthavingtwoonaline@fl(here)and@fl(there)as
wellasonethatbeginsononelineandends@fl(somewhere
onanotherline).Whatif@fl(itishere)ontheline?
Another@fl(one).
现在要作的就是将"fl@(…)替换为"\fB(…)\fR。
以下就是满足条件的sed命令:
$sed[email=]'s/@fl(\([^)]*\))/\\fB\1\\fR/g[/email]
>[url=]/@fl(.*/[/url]{
>N
>[email=s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g]s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g[/email]
>P
>D
>}'expl.6
然而,如果不使用这种输入输出循环,而是单单用N来实现的话,就会出现问题:
$sed[email=]'s/@fl(\([^)]*\))/\\fB\1\\fR/g[/email]
>[url=]/@fl(.*/[/url]{
>N
>[email=s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g]s/@fl(\(.*\n[^)]*\))/\\fB\1\\fR/g[/email]
>}'expl.6
这样的sed脚本是有漏洞的。
对行进行存储:
前面已经解释了模式空间的定义,而在sed中还有一个缓存叫作存储空间。
在模式空间和存储空间中的内容可以通过一组命令互相拷贝:
命令简写功能
Holdh或H将模式空间的内容拷贝或附加到存储空间
Getg或G将存储空间的内容拷贝或附加到模式空间
Exchangex交换模式空间和存储空间中的内容
命令的大小写的区别在于大写的命令是将源空间的内容附加到目标空间,而小写的命令则是用源空间的内容覆盖目标空间。
值得注意的是,不管是Hold命令还是Get命令,都会在目的空间的原有内容之后加上一个换行符,然后才把源空间中的内容加到换行符的后面。
从下面这个例子,可以体会这部分内容的初步应用:
例7:
$catexpl.7
1
2
11
22
111
222
我们要做的工作就是将第一行与第二行,第三行与第四行,第五行与第六行互换。
sed的命令各式是:
$sed'
>/1/{
>h
>d
>}
>/2/{
>G
>}'expl.7
这个过程是这样的:
首先,sed将第一行读入模式空间,然后h命令将其放入存储空间保存起来,一个d命令又把模式空间中的内容清空;接着sed把第二行读入模式空间,然后G命令把存储空间中的内容附加到模式空间(注意的是在模式空间的原内容末尾是加了一个换行符的)。
最后得到的结果如下:
2
1
22
11
222
111
使用H或h命令的时候,比较常见的是在这个命令之后加上d命令,这样一来,sed脚本不会到达最后,因而模式空间中的内容也就不会输出了。
另外,如果把d换作n,或者把G换作g,都不会达到目的的。
子母的大小写转换什么最方便,估计是tr了。
$tr"[a-z]""[A-Z]"File
很利害的是sed也可以完成这个转换。
相应的命令是y:
$sed'
>/[address]/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'File
然而y命令是对整个行完全进行修改,因此如果只是将行里面的几个字符变换大小写的话,这样做是行不通的。
为完成这个工作,需要借助上面刚提到的Hold和Get命令了。
catexpl.8
findtheMatchstatement
ConsulttheGetstatement
usingtheReadstatementtoretrievedata
$sed'/the.*statement/{
>h
>s/.*the\(.*\)statement.*/\1/
>y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
>G
>s/\(.*\)\n\(.*the\).*\(statement.*\)/\2\1\3/
>}'expl.8
以第一行的处理过程来说明这段命令的含意:
(1)"findtheMatchstatement"被放入存储空间;
(2)替换改行得到:
Match;
(3)将
(2)的结果转换为大写:
MATCH;
(4)从存储空间去处
(1)保留的内容附加到模式空间,此时模式空间的内容为:
MATCH\nfindtheMatchstatement
(5)再次对模式空间的内容替换得到:
findtheMATCHstatement。
下面将举到的例子要用到比较扎实的正则表达式,不过没有关系,慢慢来,一切问题都是可以解决的。
另外这个例子用到的文本主要是和编辑排版有关的,这方面我不大会,所以我就只是把sed脚本拿出来,抓住核心,省掉那些细枝末节的东西:
例9:
$catexpl.9.sed
h
s/[][\\*.]/\\&/g
x
s/[\\&]/\\&/g
s/^\.XX//
s/$/\//
x
s/^\\\.XX\(.*\)$/\/^\\.XX\/s\/\1//
G
s/\n//
(1)h:
讲文本行放入存储空间。
(2)s/[][\\*.]/\\&/g:
这个表达式难度比较大,如果在类表达,也就是"[]"中的第一个字符是"]"的话,那么"]"就丧失了它的特殊含意;另外,唉"[]"中,仅仅只有"\"是有特殊含意的,言下之意就是"*"、"."都是理解为字面意思,要使他们具有特殊意义就必须使用"\"的转义了;虽然在表达式中没有出现,也要提一下,在"[]"中只有"^"出现在第一的位置时,表示"非"的含意,其余情况就是字面解释,而"$"仅仅是在正则表达式的末尾时才有特殊含意。
"\\"去掉了"\"的特殊含意,"&"表示向前引用,因此,第二个命令的意思就是:
将模式空间中的"["、"]"、"\"、"*"、"."依次用"\["、"\]"、"\\"、"\*"、"\."来替换。
(3)x:
交换模式空间和存储空间。
执行这个命令后模式空间的内容是原文的内容,而存储空间中的内容发生变化,各个特殊字符都被替换成为了"\&"。
(4)s/[\\&]/\\&/g:
对模式空间处理,出现的"\"或者"&"都会替换为"\\"或者"\&"。
(5)s/$/\//:
这个好理解,就是在模式空间的结尾加上一个"/"。
(6)x:
再次交换两个空间的内容。
(7)s/^\\\.XX\(.*\)$/\/^\\.XX\/s\/\1//:
这个没有什么难度,就是那几个引用容易把人看晕了,仔细一点,不会有问题的,就略过吧。
(G:
略了。
(9)s/\n//:
删除换行符。
这个脚本有什么用呢?
用以下的文本实验就清楚了:
.XX"asterisk(*)metacharacter"
下面是每次命令的结果,第一行和第二行分别表示模式空间和存储空间的内容:
1..XX"asterisk(*)metacharacter"
.XX"asterisk(*)metacharacter"
2.\.XX"asterisk(\*)metacharacter"
.XX"asterisk(*)metacharacter"
3..XX"asterisk(*)metacharacter"
\.XX"asterisk(\*)metacharacter"
4..XX"asterisk(*)metacharacter"
\.XX"asterisk(\*)metacharacter"
5."asterisk(*)metacharacter"
\.XX"asterisk(\*)metacharacter"
6."asterisk(*)metacharacter"/
\.XX"asterisk(\*)metacharacter"
7.\.XX"asterisk(\*)metacharacter"
"asterisk(*)metacharacter"/
8./^\.XX/s/"asterisk(\*)metacharacter"/
"asterisk(*)metacharacter"/
9./^\.XX/s/"asterisk(\*)metacharacter"/\n/"asterisk(*)metacharacter"/
10./^\.XX/s/"asterisk(\*)metacharacter"/"asterisk(*)metacharacter"/
看到没有,其实"s/[\\&]/\\&/"没有在我们的例子中没有起作用,但是它不可少,因为在s命令的第二部分,"\"和"&"都是有特殊含意的,所以要预先转义掉其特殊含意。
明白了吗?
当你希望用一个shell脚本自动生成一个主要是替换命令的sed脚本的时候,会发现这个以上的内容对特殊字符的处理是多么得关键。
出了上面的应用,存储空间甚至还能够将很多行的内容存储起来供以后的输出。
实际上,这一功能对html等具有非常明显的结构的文本非常有效。
下面是相关的例子:
例10
catexpl.10
Mywifewon'tletmebuyapowersaw.Sheisafraidofan
accidentifIuseone.
SoIrelyonahandsawforavarietyofweekendprojectslike
buildingshelves.
However,ifImademylivingasacarpenter,Iwould
havetouseapower
saw.Thespeedandefficiencyprovidedbypowertools
wouldbeessentialtobeingproductive.
Forpeoplewhocreateandmodifytextfiles,
sedandawkarepowertoolsforediting.
Mostofthethingsthatyoucandowiththeseprograms
canbedoneinteractivelywithatexteditor.However,
usingtheseprogramscansavemanyh
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- sed 大师级 用法