首页 > 代码库 > sed(二)高级部分
sed(二)高级部分
原文是这么说的:一旦你理解了这里所给出的命令,那么就可以认为自己是真正的sed主人了
为了成为sed的主人,大伙一起努力吧
sed高级命令分为三块
处理多模式空间(N,D,P)
采用保持空间来保持模式空间的内容并使它可用于后续的命令(H,h,G,g,x)
编写使用分支和条件指令的脚本来更改控制了(:,b,t)
咱们先温习下,基础部分,sed的处理过程吧
通常来说,一行被读进模式空间,并且用脚本中的每个命令(一个接一个地)应用于该行。当到达脚本底部时,输出这一行,并清空模式空间。然后新行被读入模式空间,并且控制被转移回脚本的顶端。
也就是说,一般情况下,行的读入,命令的执行都是按照流程一步步来的。当然基础部分也有两个例外,可以改变流程。
一个是d命令,d命令将会清空模式空间,并导致读入新的输入行,此时控制将忽略d之后的命令,并转移到脚本的顶端作用在新输入行上。
第二个是n命令,可以说n命令和d命令有一点点类似,不同的是n命令执行的时候,会读入下一行替换当前行,替换之前会把当前行输出。而替换之后,n命令之后的命令会作用到新行上
多行模式空间
OK,回顾了基础篇sed的基本使用流程。下面正式走进高级篇吧
先说说什么是多行模式空间吧?
多行模式空间说白了看起来,还是一行。为什么这么说呢?
因为多行模式,是在单行的基础上读入新行,而新行的读入不会导致原本行的输出或清除。 新行和原本行以\n连接,所以连接之后的行,还是一行。
就如同读入以下三行
1
2
3
而在多行模式空间呈现给我们的是 1\n2\n3
而生成多行模式空间,离不开N这个命令
多行模式生成之后,里面多了\n,所以又多了俩命令D,P,可以针对\n参数做一些处理
其它的,咱们基础篇里面说的,还和原来一样的用。
既然说道了多行模式空间的三个命令N,D,P,那我们就来看看吧
命令 | 用法 |
N | 读取新的输入行,并将该行追加到模式空间现有内容之后,来创建多行模式空间。创建后的多行模式空间中,原有内容和新内容用换行符"\n"来分割。 而执行N命令之后,将会继续执行,N之后的命令,N之后命令的对象则是我们新的模式空间的内容。 注意:多行模式空间中,^匹配整个空间的开始,$匹配整个空间的结尾, 比如上面的 1\n2\n3 开头是1,结尾是3 $!N,最后一行,不执行N命令 |
D | 删除模式空间中,从头开始到第一个嵌入的换行符为止。 它并不会导致新行的输入,而是会返回脚本的顶端,将这些指令应用于空间中剩余的内容 |
P | 输出模式空间中,从头开始到第一个嵌入的换行符为止。 实际运用中,P经常放到N之后,P之前 |
n | 输出当前模式空间的内容,读取下一行替换当前行,替换之后,n命令之后的命令作用到新行上 |
d | 情况模式空间,并导致新行的读入,此时控制将忽略d之后的命令,并转移到脚本的顶端,作用在新的输入行上 |
p | 打印整个模式空间的内容。其他的对模式空间,没啥影响了。 |
N命令示意图:
visio流程图工具不太用户,D,和P的图,画不出来
抄书上一个例子。有以下文本
I want to see @f1(what will happen) if we put the font change commands @f1(on a set of lines). if I understand things (correctly), the @f1(third) line causes problems. (No?). ls this really the case, or is it (maybe) just something else? Let‘s test having two on a line @f1(here) and @f1(three) as well as one that begins on one line and ends @f1(somewhere on another line). What if @f1(it is here) on the line? Another @f1(one).
现在我们需要文本中所有的,把@f1(anything)形式的内容,替换为\fB(anything)\fR的形式。 不管,
@f1(anything)是跨行还是非跨行的。。。。像第二大端,第二行,就属于跨行的了。。。我们用基础部分sed功能,是无法处理的。。。。下面看看,怎么完成要求的吧?
先看一下代码吧
root@salt-master:~/sedAawk/sed# sed ‘ > s/@f1(\([^)]*\))/\\fB\1\\fR/g 1 > /@f1(.*/{ 2 > N 3 > s/@f1(\(.*\n[^)]*\))/\\fB\1\\fR/g 4 > P 5 > D 6 > }‘ xiti 7
第1行s/@f1(\([^)]*\))/\\fB\1\\fR\g
pattern部分为/@f1(\([^)]*\))/,匹配的结果为@f1(anything),但是不包括@f1(...)...)这种形式
这么做是为了,避免第一大段第3行的的这种情况,正则表达式默认是最大匹配,如果不加[^)],
"@f1(third)"会被匹配成"@f1(third) line causes problems. (No?)".
replacement部分为"\\fB\1\\fR",\1用来替换前面pattern里面定义的分组
这第一个sed命令要干的活,显然是把文本中,非跨行的匹配给搞定。
第3行,是第2个sed指令的地址
第4行,使用N命令,读取下一行
第5行,"s/@f1(\(.*\n[^)]*\))/\\fB\1\\fR\g"
pattern部分为"/@f1(\(.*\n[^)]*\))/",N命令执行后,原本的行和新读取的行,会被用\n连接。所
以这地方,我们匹配的时候要注意\n。其它和第1个sed命令一样
replacement部分和第1个sed指令一样,用到了前面的分组
第6行,输出模式空间中,开始到第一个\n之间的内容。
第7行,删除模式空间中,开始到第一个\n之间的内容,控制返回脚本顶部,作用与剩余的内容
第6行,和第7行,结合在一起。 如果不加这两个命令的话,当sed的第1个命令作用于第二段第2行时,未匹配,则继续执行sed的第二个命令,此时匹配成功。。。N命令读取第二段第3行。
N命令后的替换命令会把第二段2行末尾和第二段3行开头的那东西替换掉,但是如果此时未作P,和D操作的话,读入的这两行将会被直接输出。 此时,第二段3行的@f1(it is here)并未被修改。
加上P,和D的作用就是,先把第二段2行打印出来,此时执行命令D,删除第二段2行,控制返回sed脚本顶部,第一个sed命令作用于第二段3行,替换完毕。
上面的N,P,D的模型,是经常会用到的一个模型,可以达到循环控制的效果
保持空间
保持空间,是sed高级篇的第二部分。
模式空间和保持空间有啥区别呢?
其实没啥区别,两个空间就是两块指向不同地址空间的内存,就是两个空间里面干的活不一样。
说白了,保持空间就是给模式空间,临时存数据用的。
模式空间,可以把内容放到保持空间里面,也可以从保持空间里面拿内容,模式空间和保持空间也可以相互交换内容。
命令 | 缩写 | 说明 |
Hold | h或H | 将模式空间的内容复制或追加到保持空间 |
Get | g或G | 将保持空间的内容复制或追加到模式空间 |
Exchange | x | 将模式空间和保持空间的内容相互交换 |
先说说Hold命令
h和H是有区别的,h会改写保持空间原因的内容,H则是把内容追加到保持空间。
注意:Hold命令执行的时候,不管保持空间是否为空先往保持空间里面扔个\n进去,然后再把内容放进去。
再说说Get命令
和Hold一样,g和G是有区别的,g会改写模式空间的内容,G则是把保持空间的内容追加到模式空间
注意:和Hold命令一样,会先扔个\n到模式空间里面去
Exchange则是交互保持空间和模式空间的内容。 连同\n等全部内容都要交换,所以
例子
My wife won‘t let me buy a power saw. She is afraid of an accident if I use one. So i rely on a hand saw for a variety of weekend projects like building shelves. However, if I made my living as a carpenter, I would have to use a power saw. The speed and efficiency provided by power tools would be essential to being productive. For people who create and modify text files, sed and awk are power tools for editing. Most of the things that you can do with these programs can be done interactively with a text editor. However, using these programs can save many hours of repetitive work in achieving the same result.
空行分开的,为一个段落。。。。现在要求,在段落的其实加上<p>,锻炼的结尾加上</p>
脚本
root@salt-master:~/sedAawk/sed# sed ‘/^$/!{ 1 H 2 d 3 } 4 /^$/{ 5 x 6 s/^\n/<p>/ 7 s/$/<\/p>/ 8 G 9 }‘ HTML 10
第1-4行,为第一个sed指令,作用:匹配到非空行,则把该行追加到保持空间,然后删除模式空间,并输入新行。
注意,模式空间内容追加到保持空间之前,会先在保持空间中放入"\n",即使保持空间是空的,也会先放入"\n"
5-10行为sed第二个指令,作用:匹配到空行,则把模式空间和保持空间的内容互换。
此时,保持空间的内容变为^$,
模式空间内容变为\n.*
7行,模式空间中\n开头的行,把\n替换为<p>,因为第一条sed指令,追加模式空间内容到保持空间的时候,保持空间的内容开头肯定会有"\n"。。。第二条指令互换后,内容如开头也会有"\n"
8行,在内容结尾处,加上</p>。 $,当我们用l列表的形式查看的时候,都会有这么个东西。
分支和测试
三个名词
分支branch(b)
测试test(t)
标签(label) 标签名字任意以":"开头,长度不超过7个字符。如":top",": "和 top直接不要有空格
说说什么是分支和测试,用法?
分支b,测试t和p,n,d这些都一样是个命令。
一般来说b,t会合标签在一起使用
使用形式:[address]b[label] [address]t[label]
当b,t后面加上标签的时候,指令就不安装正常流程执行了。而是,跳转到标签处继续执行标签后面的指令。
当b,t后面不加标签的时候,会直接跳转到脚本的最底部。。。
这东西就是c语言的goto一个样。
再说说b和t有什么区别?
b是无条件执行的,也就是说,就要执行到指令b,则肯定会跳转
而t则是有条件,什么条件呢?
条件是看t前面的替换操作是否成功,成功则跳转,不成功则不跳转。 替换就是咱们前面说的s///
其实方面,b,t都差不多了。
三种常用形式:
:top 1 command1 2 command2 3 /pattern/b top 4 command3 5
这个指令,command1和command2肯定会执行的,除非在1-4行形成了死循环,否则command3也会执行的
区别是command3执行一次,而command1和command2则执行至少一次
command1 1 /pattern/b end 2 command2 3 :end 4 command3 5这个指令,command1肯定会被执行,command2则在2行不匹配的情况下才会被执行,command3则肯定会被执行
command1 1 /pattern/b dothere 2 command2 3 b 4 :dothere 5 command3 6
这个指令,command1肯定会被执行,command2和comand3只有一个会被执行。。。
第2行和第4行,类似于if...else...条件选择,而command3和command2分别是他们的执行模块。
所以只会有一个被执行。
t命令和b类似,唯一的区别是t多了重条件。
来个例子
和上面的模式空间是同一个例子,不过要求不同
I want to see @f1(what will happen) if we put the font change commands @f1(on a set of lines). if I understand things (correctly), the @f1(third) line causes problems. (No?). ls this really the case, or is it (maybe) just something else? Let‘s test having two on a line @f1(here) and @f1(three) as well as one that begins on one line and ends @f1(somewhere on another line). What if @f1(it is here) on the line? Another @f1(one).
要求:模式空间里面的例子,我们是使用D这个命令来做的流程控制,这里面的要求是我们使用b和t做流程控制。
看一下,脚本。
root@salt-master:~/sedAawk/sed# sed ‘ :begin /@f1(\([^)]*\))/{ s//\\fB\1\\fR/g b begin } /@f1(.*/{ N s/@f1(\([^)]*\n[^)]*\))/\\fB\1\\fR/g t again b begin } :again P D‘ xiti
OK,到这里吧,sed功能差不多就这些了。。。都不难,关键是看怎么组合使用了。。。写个几行的sed脚本想必,大多数人都写的出来。。。但是要写到几十上百行,想必能够做到人,要被砍掉一大批了。
本文出自 “西风” 博客,请务必保留此出处http://lixcto.blog.51cto.com/4834175/1436452