原文地址:sed实例精解--例说sed完整版 作者:xiaozhenggang
最近在学习shell,怕学了后面忘了前面的就把学习和实验的过程记录下来了。这里是关于sed的,前面有三四篇分开的,现在都把它们弄到了一起,并做了一些调整,二十多页,有点长啦。不过大部分都是例子来着,呵呵。
在电脑前坐太久了还真是不行,脖子都歪啦!强烈建议各位找点时间多动动,多动动!还是身体重要嘛!!!
我的实验环境是: fedora 14 ,bash。
在实验中遇到了一些问题,都在后面的例子中提到啦。有些问题纠结了好久,才发现只是多了或少了一个空格的问题,汗......
这中间肯定还有很多问题,热烈欢迎各位赐教!
路才开始,努力,坚持,加油!!!
例说sed
sed:stream editor
流线型,非交互式的编辑器。它每次只处理一行文件并把输出打印到屏幕上。
Pattern space: 模式空间即存放当前正在处理的行的缓存空间。 一旦处理工作完成,sed就会把结果输出到屏幕,然后清空模式空间并把下一行读入模式空间,进行相关处理;直到最后一行。
sed是无破坏性的,它不更改原文件,除非你使用重定向保存输出结果。
对于一行文本,sed命令是依次执行的,如果有多个命令的话。这时,要注意各命令之间可能产生的相互影响。
对于多个sed命令,我们可以用“{}”把它们括起来。但要注意,右花括号一定要单独成行。
sed命令后不能有空格,前面则无所谓。
我们可以把一系列的sed命令写入文件中并用sed 的-f选项调用
好啦,打住先(没提到的后面都会有例子说明的,嘿嘿)
首先,我们来看看sed的语法及寻址方式:
语法:
sed [options] 'command' filename(s)
寻址方式:
1.单行寻址:[line-address]command;寻找匹配line-address的行并进行处理。
2.行集合寻址:[regexp]command ;匹配文件中的一行或多行,如/^A/command匹配所有以A开头的行。
3.多行寻址: [line-address1,line-address2] command;寻找在两个地址之间的内容并做相应的处理。
4.嵌套寻址:10,20{
/^$/d
#上面三种寻址方法都可以应用在这里
}
接下来,瞧瞧sed的一些命令和选项
sed选项:
选项 |
功能 |
-e |
允许多次编辑 |
-f |
跟随脚本文件名 |
-n |
禁止默认输出 |
sed的相关命令:
命令 |
功能 |
a |
向当前行添加文本行 |
c |
用新的文本行取代当前行里的文本 |
i |
在当前行之前插入文本 |
d |
删除行 |
h |
把模式空间内容复制到一个固定缓存 |
H |
把模式空间内容添加到一个固定缓存 |
g |
把固定缓存里的所有文本都复制到模式缓存,重写模式缓存的内容 |
G |
把固定缓存里的所有文本添加到模式缓存 |
l |
列出不打印的字符 |
p |
打印行 |
P(大写) |
多行打印,输出多行模式空间里的第一部分,直到第一个嵌入的换行符为止 |
n |
输出模式空间的内容并读取下一行 |
N |
读取新的输入行并将其添加到模式空间的现有内容之后来创建多行模式空间 |
q |
结束或退出 |
r |
读入行,从某个文件 |
! |
把命令应用到选定行之外的其它所有行 |
s |
替换 |
替换标志:
标志 |
功能 |
g |
全局替换 |
p |
打印 |
w |
把行写到文件中 |
x |
交换;用模式空间的内容交换固定缓存的内容 |
y |
转换,如大小写转换 |
sed支持的一些元字符:
元字符 |
功能 |
例 |
^ |
定位行开头 |
/^sed/:匹配所有以sed开头的行 |
$ |
定位行结尾 |
/sed$/:匹配所有以sed结尾的行 |
. |
匹配单个字符,不包括换行符 |
/s.d/:匹配包含一个s,后跟一个字符,再跟一个e的行 |
* |
匹配零个或多个字符 |
/*sed/:匹配的行有零个或多个空格且其后跟模式sed |
[] |
匹配集中的一个字符 |
/[Ss]ed/:匹配包含sed或Sed的行 |
[^] |
反上 |
/[^Ss]ed/:匹配的行不包含s,S且后跟ed |
(..) |
保存被匹配的字符 |
s/(love)/1 ly/:用lovely取代love。把被标志的部分标为1,以后就能用1引用。最多允许使用9个标记,第一个从模式的最左端开始。如上面的love就保存在寄存器1里且被记在替换串里。 |
& |
保存搜索串以便记在替换串里 |
s/sed/fuck&/:&代表搜索串sed。此例中sed将被fucksed替换 |
< |
定位词开头 |
/<sed/:匹配以sed开头的一个词 |
> |
定位词结尾 |
/sed>/:匹配以sed结尾的一个词 |
x{m} |
字符x重复m次 |
o{3}:匹配的行里o要连续出现3次 |
x{m,} |
字符x至少重复m次 |
o{3,}:匹配的行里o至少要连续出现3次 |
x{m,n} |
字符x至少重复m次且不超过n次 |
O{3,5}:匹配的行里要o至少要连续出现3次但不超过5次 |
好啦,下面就有例子来说话喔,呵呵
datafile的内容:
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
e.g. 1:
a--找到以north开头的行并在其后添加很多FUCK
[fedora@novice chap04]$ sed '/^north/aFUCK FUCK FUCK FUCK kcuf kcuf kcuf kcuf' datafile
northwest NW Charles Main 3.0 .98 3 34
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
north NO Margot Weber 4.5 .89 5 9
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
central CT Ann Stephens 5.7 .94 5 13
***************************************************************************************************
发现在bash中只能像上面那样输入且a后的可有可无 ; 并不像书上说的那样,不知是不是跟SHELL有关系
一般,a后是要带的,有时还要带两个。如果要添加的文本不止一行的话,除了最后一行每一行的结尾都要跟。以上只是在控制台输入,在脚本中输入的情况还是和书上说的一样的。
***************************************************************************************************
e.g. 2:
i --在以central开头的行前分行插入FUCK
[fedora@novice chap04]$ sed '/central/iF U C K' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
F
U
C
K
central CT Ann Stephens 5.7 .94 5 13
***************************************************************************************************
一般,如果要添加的文本不止一行的话,除了最后一行每一行的结尾都要跟。但在我这里好像有点不一样,在终端直接输入时。
****************************************************************************************************
e.g. 3:
c--把有sourth的行全部用FUCK取代
[fedora@novice chap04]$ sed '/south/cFUCK' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FUCK
FUCK
FUCK
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
****************************************************************************************************
*其它与e.g.1 ,e.g. 2 类似
****************************************************************************************************
e.g. 4:
d--删除第一行
[fedora@novice chap04]$ sed '1d' datafile
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
d--删除1-4行
[fedora@novice chap04]$ sed '1,4d' datafile
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
d--删除有north的行
[fedora@novice chap04]$ sed '/north/d' datafile
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
central CT Ann Stephens 5.7 .94 5 13
***************************************************************************************************
e.g. 5:
s--替换。用FUCK替换north.
[fedora@novice chap04]$ sed 's/north/FUCK/' datafile
FUCKwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
FUCKeast NE AM Main Jr. 5.1 .94 3 13
FUCK NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
s--替换。用FUCK替换所有以south开头的行中的south.
[fedora@novice chap04]$ sed '/^south/s/south/FUCK/g' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FUCKwest SW Lewis Dalsass 2.7 .8 2 18
FUCKern SO Suan Chin 5.1 .95 4 15
FUCKeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
s--替换。 寻找大于1少于10的一位小数并用FUCK+&替代。这里的&保存了前面的小数
[fedora@novice chap04]$ sed 's/[0-9].[0-9]/FUCK&/' datafile
northwest NW Charles Main FUCK3.0 .98 3 34
western WE Sharon Gray FUCK5.3 .97 5 23
southwest SW Lewis Dalsass FUCK2.7 .8 2 18
southern SO Suan Chin FUCK5.1 .95 4 15
southeast SE Patricia Hemenway FUCK4.0 .7 4 17
eastern EA TB Savage FUCK4.4 .84 5 20
northeast NE AM Main Jr. FUCK5.1 .94 3 13
north NO Margot Weber FUCK4.5 .89 5 9
central CT Ann Stephens FUCK5.7 .94 5 13
****************************************************************************************************
刚开始时用的是下面的语句:
sed '[0-9][0-9]$/FUCK&/' datafile,怎么弄都不成功。
不知是怎么回事。
*****************************************************************************************************
e.g. 6:
p--打印:默认打印所有的行。这里用-n选项过滤无关的行
[fedora@novice chap04]$ sed -n '/north/p' datafile
northwest NW Charles Main 3.0 .98 3 34
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
发现一个问题:p也会把匹配的行打印两次:
[fedora@novice chap04]$ sed '/north/p' datafile
northwest NW Charles Main 3.0 .98 3 34
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94
也就是说不使用-n选项的话,p会打印出匹配两次
P--多行打印:在执行完所有命令后模式空间的内容会自动输出,在下面的例子中可以看到匹配的行输出了两次,但是-n选项会抑制这个动作。只有在与D,N配合使用时才会输出模式空间里的第一行,此时不用-n选项。
[fedora@novice chap04]$ sed '/north/P' datafile
northwest NW Charles Main 3.0 .98 3 34
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
****************************************************************************************************
e.g. 7:
D--多行删除:选项看到d与D的不同之处了么?其中空行分别为1,2,3,4行。
[fedora@novice chap04]$ cat >test
this is a test line
this is a test line
this is a test line
this is a test line
this ia a test line
[fedora@novice chap04]$ sed -e '/^$/N' -e '/^ $/d' test
this is a test line
this is a test line
this is a test line
this is a test line
this ia a test line
[fedora@novice chap04]$ sed -e '/^$/N' -e '/^ $/D' test
this is a test line
this is a test line
this is a test line
this is a test line
this ia a test line
****************************************************************************************************
可以看到,与N配合的情况下:
使用d,若有偶数个空行将会全被删除,若有奇数个空行将会保留一行。这是因为d删除的是整个模式空间的内容。一旦遇到第一个空行就马上读入下一行,然后两行都删除。如果第三行为空且下一行不为空则命令不执行,空行被输出。
使用D,当遇到两个空行时D会删除两个空行中的第一个,然后再读入下一行,如果是空行则删除第一行,如果空行后有文本则模式空间可以正常输出。
***************************************************************************************************
e.g. 8:关于N命令与-e选项在上面已在应用,这里就不举例啦,偷点懒哈,嘿嘿。
*****************************************************************************************************
e.g. 9:
r--从文件中读取:从test中读取相关的内容添加到datafile中所有匹配的行的后面。
[fedora@novice chap04]$ sed '/^south/r test' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
**********************************
FUCK FUCK FUCK FUCK ,FUCK TOO MUCH
**********************************
southern SO Suan Chin 5.1 .95 4 15
**********************************
FUCK FUCK FUCK FUCK ,FUCK TOO MUCH
**********************************
southeast SE Patricia Hemenway 4.0 .7 4 17
**********************************
FUCK FUCK FUCK FUCK ,FUCK TOO MUCH
**********************************
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
***************************************************************************************************
e.g. 10
w--写入文件:把datafile中所有匹配的行写入到test文件中
[fedora@novice chap04]$ sed '/^south/w test' datafile|cat test
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
***************************************************************************************************
e.g. 11
n--next:如果有能匹配western行,则n命令使得sed读取下一行,然后执行相应命令
[fedora@novice chap04]$ sed -e '/western/n' -e 's/SW/FUCK/' datafile|head -n 4
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest FUCK Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
***************************************************************************************************8
e.g. 12
y--变换:
[fedora@novice chap04]$ sed '3,5y/s/S/' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
SouthweSt SW LewiS DalSaSS 2.7 .8 2 18
Southern SO Suan Chin 5.1 .95 4 15
SoutheaSt SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
[fedora@novice chap04]$ sed '1y/3/9/' datafile
northwest NW Charles Main 9.0 .98 9 94
western WE Sharon Gray 5.3 .97 5 23
***************************************************************************************************
替换的类型要一致,数字与字母之间不能相互替换。
且对正则表达式的元字符不起作用。
*****************************************************************************************************
e.g. 13:
q--退出:
打印三行后退出
[fedora@novice chap04]$ sed '3q' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
用相应的字符做出替换后退出
[fedora@novice chap04]$ sed -e 'y/northwest/ABCDEFGHI/' -e q datafile
ABCDEFGHD NW CEaClGH MaiA 3.0 .98 3 34
这样也可以的
[fedora@novice chap04]$ sed '{ y/northwest/ABCDEFGHI/; q;}' datafile
ABCDEFGHD NW CEaClGH MaiA 3.0 .98 3 34
多个命令写在一行时可以用-e选项,也可以用花括号把所有命令括起来并用分号隔开且最后一个分号可有可无,在我的实验环境下。
**************************************************************************************************
e.g. 14:
H/h/G/g--保存和取得
下面是这几个命令的一些组合,能看出些什么来么?
[fedora@novice chap04]$ sed -e '/northeast/h' -e '$g' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
northeast NE AM Main Jr. 5.1 .94 3 13
[fedora@novice chap04]$ sed -e '/northeast/h' -e '$G' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
northeast NE AM Main Jr. 5.1 .94 3 13
[fedora@novice chap04]$ sed -e '/northeast/H' -e '$g' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
northeast NE AM Main Jr. 5.1 .94 3 13
[fedora@novice chap04]$ sed -e '/northeast/H' -e '$G' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
northeast NE AM Main Jr. 5.1 .94 3 13
因为呢,H/G在相应空间的内容之后放置一个换行符,且后面紧跟模式空间的内容;而g/h的呢都是取代相应空间的内容,所以就有上面的不同结果喔
***************************************************************************************************
e.g. 15
x--交换模式/保持空间内容
首先匹配第一个包含north的行放入保持缓存,然后匹配第一个包含south的行放入模式空间,最后把两者的内容交换。
[fedora@novice chap04]$ sed -e '/north/h' -e '/south/x' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
****************************************************************************************************
e.g. 16
sed脚本:
[fedora@novice chap04]$ vim sedlist
/central/a
------This is a test--------
/northeast/i
------This is a test too------
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
------This is a test too------
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
------This is a test--------
可以在里面添加注释,以#开头的行被认为是注释
如有多行,则每行都要以结尾,除了最后一行。如,下面的脚本是可以正常执行的。
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands list
/central/a
------This is a test too--------
------Hi am here----------------
#now ,the second test
/northeast/i
------This is a test ------
***************************************************************************************************
****************************************************************************************************
*******************************************************************************************************
高级流控制命令
b 分支 :无条件转移
t 测试 :有条件的转移
它们将脚本中的控制转移到包含特殊标签的行;如果没有标签则直接转移到脚本的末尾。只有当替换命令改变当前行时才会被执行。
标签:任意的字符组合且长度不大于7,它本身占据一行且以冒号开头
:mylabel
冒号和标签之间不能有空格,标签后的空格会被当做标签的一部分。
标签和命令之间允许有空格。
b 分支:[address] b [label]
b --> branch,在脚本中将控制权转到另一行,通过它你可以跳到你想去的地方,是不是有点像c中的goto呀?
它可以将一组命令当做一个过程来执行且这个过程在脚本中可以重复执行,只要条件满足。
e.g 17
b--分支
看下面的例子:
e.g. 17.1
匹配以north加空格开头的行,若匹配则转到:label后面的命令,在以s开头的行前插入FFFFFFFFFFFFFFUCK ;
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
:label
/^s/i
FFFFFFFFFFFFFFUCK
/^north / b label
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FFFFFFFFFFFFFFUCK
southwest SW Lewis Dalsass 2.7 .8 2 18
FFFFFFFFFFFFFFUCK
southern SO Suan Chin 5.1 .95 4 15
FFFFFFFFFFFFFFUCK
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
其实这也是个循环,反复执行两个标签间的命令,直到模式不匹配。但是,如上,不管匹配与否两个标签间的内容至少会被执行一次。也就是说,正常情况下上面的命令都会被执行一次。看下面的例子:
e.g 17.2
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
:label
/^n/d
/^A/b label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
看到了吧!虽然模式不匹配,但还是执行了两个标签间的内容,嘿嘿!再看看上面,和do-while语句有什么异同?
e.g. 17.3
如果匹配,什么都不做,否则执行后的命令向以cent开头的行后添加一些内容
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
:label
/^A/b label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
e.g. 17.4
另一种循环模式
command1
/pattern/b label
command2
label:
command3
首先执行command1,然后看模式是否匹配,若匹配则执行command3,否则执行command2,command3
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
/^n/d
/^A/b label
s/south/SSSSSS/
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
western WE Sharon Gray 5.3 .97 5 23
SSSSSSwest SW Lewis Dalsass 2.7 .8 2 18
SSSSSSern SO Suan Chin 5.1 .95 4 15
SSSSSSeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
模式不匹配,顺序执行各命令,下面来看匹配的情况:
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
/^w/d
#north后有一个空格
/^north /b label
s/south/SSSSSS/
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
SSSSSSwest SW Lewis Dalsass 2.7 .8 2 18
SSSSSSern SO Suan Chin 5.1 .95 4 15
SSSSSSeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
很显然,这里并没有跳过第二个命令,但是理论上只模式空间匹配的话就会直接转到:label后的命令的呀!这到底是为什么呢?我们来看下一个脚本,只对上个脚本做一点点修改:
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
/^w/d
#north后有一个空格
/^north /b label
s/north /SSSSSS/
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
这次结果正常啦,它找到了以north加空格开头的行,并跳过了第二个命令。
再来看两个例子:
在第二个命令后再添加一个命令s/south/NNNNNN看会有怎样的结果:
[fedora@novice chap04]$ cat sedlist
#This script is a test for sed commands
/^w/d
/^north /b label
s/north /SSSSSS/
s/south/NNNNNN/
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW Charles Main 3.0 .98 3 34
NNNNNNwest SW Lewis Dalsass 2.7 .8 2 18
NNNNNNern SO Suan Chin 5.1 .95 4 15
NNNNNNeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
显然,s/north /SSSSSS/ 没有被执行而s/south/NNNNNN/ 被执行啦
又一个例子:
[fedora@novice chap04]$ cat sedlist1
#This script is a test for sed commands
/^w/d
/^north/b label
p
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist1 datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
可以看到p应用到了除以north开头的所有行!再来一个例子:
[fedora@novice chap04]$ cat sedlist1
#This script is a test for sed commands
/^w/d
/^north/b label
p
l
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist1 datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southwest SW Lewis Dalsass 2.7 .8 2 18 $
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southern SO Suan Chin 5.1 .95 4 15 $
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
southeast SE Patricia Hemenway 4.0 .7 4 17 $
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
eastern EA TB Savage 4.4 .84 5 20 $
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
central CT Ann Stephens 5.7 .94 5 13 $
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!
看到了么?P,l都只应用到了除以north开头的所有行上!!!
从上面的一堆例子中,可以得到:在
command1
/pattern/b label
command2
label:
command3
模式中 只有 针对 匹配pattern的行 的操作才会被跳过!
e.g. 17.5
如何指定执行上例中的command2或command3中的一个
commmand1
/pattern/b label
command2
b
:label
command3
首先执行command1,然后执行/pattern/b label,如果模式匹配则直接跳到command3并执行相关命令,否则跳到command2在执行完相关命令后遇到分支b,分支b将控制转到脚本的结尾,绕过了command3.
下面看一个简单的例子:
[fedora@novice chap04]$ cat sedlist1
#This script is a test for sed commands
/^e/d
/^DDD/b label
s/west/SSSSSS/
b
:label
/^cent/a
--FUCK!!!
Just a test!
Take it easy!!!
[fedora@novice chap04]$ sed -f sedlist1 datafile
northSSSSSS NW Charles Main 3.0 .98 3 34
SSSSSSern WE Sharon Gray 5.3 .97 5 23
southSSSSSS SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
是吧,果然当模式不匹配时只执行command2而:label后的命令没有被执行,哈哈
e.g. 18
t: [address] t [label]
t-->test,如果在当前匹配的行上成功地进行了替换,那么t命令就转到标签处或脚本末尾(未给定标签默认指向脚本末尾)。
t要单独成行
下面来一个简单的例子:
[fedora@novice chap04]$ cat sedlist
/^s/d
/^west/s/west/QQQ/
t label1
/^n/y/nort/FUCK/
t label
:label
/^F/y/FUCK/nort/
:label1
/^QQQ/s/QQQ/west/
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW rharles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
[fedora@novice chap04]$ cat sedlist
/^s/d
/^west/y/Q/a/
t label1
/^n/y/nort/FUCK/
t label
:label
/^F/y/FUCK/nort/
:label1
/^n/y/FUCK/nort/
[fedora@novice chap04]$ sed -f sedlist datafile
northwest NW rharles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
看出两者的区别了么?我相会的,嘿嘿