Chinaunix首页 | 论坛 | 博客
  • 博客访问: 579657
  • 博文数量: 84
  • 博客积分: 1529
  • 博客等级: 上尉
  • 技术积分: 1482
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-27 17:57
文章分类

全部博文(84)

文章存档

2014年(7)

2013年(9)

2012年(20)

2011年(48)

分类: Python/Ruby

2011-12-29 17:50:23

 最近在处理一个文本,打算用sed命令来处理,但是由于经常情况下都是做简单的替换,所以对sed不是很熟悉,最近两天由于项目工作量比较小,所以就今天抽空整体学习下了sed。
先说下自己遇到处理的一个问题:
例子:
文件内容:testfile
abc
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
处理结果:获取abc到dfg之间的内容,不包括abc和dfg这两行,想要sed直接一句话处理一直有问题,所以等整体学习下sed,我们再来提出一个解决问题的方法吧。

1、sed 的工作原理
sed把当前正在处理的行保存在一个临时缓冲区中,这个缓冲区称为临时空间或者模式空间,sed处理完模式空间中的行后,就把该行发送到屏幕上,并将该行从模式空间中删除

2、把正则表达式分隔符换成另外一个字符,比如h,只要在这个字符的前面加一个反斜杠,在正则表达式后面也更上这个字符就可以了,例子:
[root@xm_41 tmp]# sed -n '/abc/p' testfile
abc
[root@xm_41 tmp]# sed -n '\habchp' testfile
abc
注:如果斜杠本身是正则表达式的一部分,必须在它们面前加上反斜杠,以免和分隔符混淆,此时就可以采用上面的这种方法。

3、sed返回码
如果在指定的文件中找到指定的模式,grep将返回码退出状态0,如果没有找到则为1,sed不一样,不管是否找到指定的模式,只要语法不出错都是返回0。
[root@xm_41 tmp]# grep 'beauty' testfile 
[root@xm_41 tmp]# echo $?
1
[root@xm_41 tmp]# sed -n '/beauty/p' testfile 
[root@xm_41 tmp]# echo $?
0

4、定址
决定对那些进行编辑,地址可以是数字、正则表达式以及两者的结合
[root@xm_41 tmp]# sed '1,2d' testfile 
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
[root@xm_41 tmp]# sed -n '/[ab]/p' testfile 
abc
     aaaaaaaaaa
     bbbbbbbbbb

5、命令和选项
 命令  功能 
a\  在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行
c\  用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行 
i\  在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行 
d  删除行 
h  把模式空间里的内容复制到暂存缓冲区 
H  把模式空间里的内容追加到暂存缓冲区 
g  把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容 
G  把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面 
l  列出非打印字符 
n  读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理 
q  结束或退出sed 
r  从文件中读取输入行 
!  对所选行以外的所有行应用命令 
s  用一个字符串替换另一个 

g  在行内进行全局替换 
p  打印行
w  将所选的行写入文件 
x  交换暂存缓冲区与模式空间的内容 
y  将字符替换为另一字符(不能对正则表达式使用y命令)

6、元字符
 元字符  功能  示例 
^  行首定位符  /^my/  匹配所有以my开头的行 
$  行尾定位符  /my$/  匹配所有以my结尾的行 
.  匹配除换行符以外的单个字符  /m..y/  匹配包含字母m,后跟两个任意字符,再跟字母y的行 
*  匹配零个或多个前导字符  /my*/  匹配包含字母m,后跟零个或多个y字母的行 
[]  匹配指定字符组内的任一字符  /[Mm]y/  匹配包含My或my的行 
[^]  匹配不在指定字符组内的任一字符  /[^Mm]y/  匹配包含y,但y之前的那个字符不是M或m的行 
\(..\)  保存已匹配的字符  1,20s/\(you\)self/\1r/  标记元字符之间的模式,并将其保存为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第20行进行处理,you被保存为标签1,如果发现youself,则替换为your。 
&  保存查找串以便在替换串中引用  s/my/**&**/  符号&代表查找串。my将被替换为**my** 
\<  词首定位符  /\ 
\>  词尾定位符  /my\>/  匹配包含以my结尾的单词的行 
x\{m\}  连续m个x  /9\{5\}/ 匹配包含连续5个9的行 
x\{m,\}  至少m个x  /9\{5,\}/  匹配包含至少连续5个9的行 
x\{m,n\}  至少m个,但不超过n个x  /9\{5,7\}/  匹配包含连续5到7个9的行 

7、sed选项
-e 允许多项编辑
-f 指定sed脚本文件名
-n 取消默认的输出

8、sed范例
(1)、d用于删除输入的行,$代表文件的最后一行
[root@xm_41 tmp]# sed '2,$d' testfile 
abc
(2)、对于s替换命名,紧跟s后面的字符就是查找和替换的分隔符
[root@xm_41 tmp]# sed -n 's/abc/china/p'  testfile 
china
[root@xm_41 tmp]# sed -n 's=abc=china=p' testfile 
china
上面用符号'='作为分隔符
(3)、r命令是读命令,读取文件内容追加到另外一个文件
[root@xm_41 tmp]# cat data
china china
[root@xm_41 tmp]# sed '/abc/r data' testfile 
abc
china china
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
读取data中的内容追加到testfile中
(4)、w是写的内容
[root@xm_41 tmp]# sed '/abc/w newdata' testfile 
abc
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
[root@xm_41 tmp]# cat newdata 
abc
(5)、a命令
[root@xm_41 tmp]# sed '/abc/a\china' testfile 
abc
china
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
(6)、i命令
[root@xm_41 tmp]# sed '/abc/i\china' testfile 
china
abc
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
(7)、c命令
[root@xm_41 tmp]# sed '/abc/c\china\' testfile 
china
     aaaaaaaaaa
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
注意:a和i的区别就是一个插入在后面一个是插入在前面,而c直接是替换掉整行,和s差别是s是替换匹配的
(8)、获取下一行:n的命令和N命令
两者命令的区别是n是读取下一行到模式空间,会替换掉原的行,而N是读取下一行追加到模式缓冲区,相当于此时模式空间中会有两行
[root@xm_41 tmp]# sed '/abc/{n;s/a/q/g}' testfile 
abc
     qqqqqqqqqq
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
[root@xm_41 tmp]# sed '/abc/{N;s/a/q/g}' testfile 
qbc
     qqqqqqqqqq
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
对于n命令来说只有第二行的a被替换成了q,而对于N命令来说一二两行的a都替换成了q
(9)、y命令
[root@xm_41 tmp]# sed '1,2y/a/A/' testfile 
Abc
     AAAAAAAAAA
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
有点和tr命令类似
引申:学习下tr命令
a、替换
[root@xm_41 tmp]# tr "a" "A" < testfile 
Abc
     AAAAAAAAAA
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
b、去除重复的字符
[root@xm_41 tmp]# tr -s "a" < testfile 
abc
     a
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk

注意:tr -s "\n" < testfile 可以去除空行
c、删除指定的字符
[root@xm_41 tmp]# tr -d "a" < testfile 
bc
     
     bbbbbbbbbb

dfg
     jjjjjjjjj
hjk
d、c命令,去反义
[root@xm_41 tmp]# tr -cd "a\n" < testfile 
a
aaaaaaaaaa

(9)、q命令直接退出不在往下执行
(10)、h和H命令:把模式空间的数据放到缓冲区中去
[root@xm_41 tmp]# sed '/abc/h;/dfg/h;g' testfile 
abc
abc
abc
abc
dfg
dfg
dfg
[root@xm_41 tmp]# sed '/abc/h;/dfg/H;g' testfile 
abc
abc
abc
abc
abc
dfg
abc
dfg
abc
dfg

注意:h和H的区别,一个是替换缓冲区的内容,一个是把内容追加到缓冲区
(11)、g命令和G命令:从缓冲区中取出展示到模式空间
[root@xm_41 tmp]# sed '/abc/h;g' testfile 
abc
abc
abc
abc
abc
abc
abc

[root@xm_41 tmp]# sed '/abc/h;G' testfile 
abc
abc
     aaaaaaaaaa
abc
     bbbbbbbbbb
abc

abc
dfg
abc
     jjjjjjjjj
abc
hjk
abc

注意:g和G区别一个是替换一个是追加

(12)、x命令:缓冲区和模式空间的数据替换
[root@xm_41 tmp]# sed '/abc/h;/dfg/x' testfile 
abc
     aaaaaaaaaa
     bbbbbbbbbb

abc
     jjjjjjjjj
hjk

(13)、显示行号
[root@xm_41 tmp]# sed = < testfile | sed 'N;s/\n/:/' 
1:abc
2:     aaaaaaaaaa
3:     bbbbbbbbbb
4:
5:dfg
6:     jjjjjjjjj
7:hjk

(14)、P命令:只输出模式空间中的第一行
[root@xm_41 tmp]# sed 'N;P' testfile 
abc
abc
     aaaaaaaaaa
     bbbbbbbbbb
     bbbbbbbbbb

dfg
dfg
     jjjjjjjjj
hjk
详解:所先sed读取第一行,然后N命令在读取一行变成abc\naaaaaaa\n,然后P打印出abc这行,当前行处理输出abc\naaaaa\n;接下去N命令在读取bbbbbbb;循环下去
[root@xm_41 tmp]# sed 'N;p' testfile 
abc
     aaaaaaaaaa
abc
     aaaaaaaaaa
     bbbbbbbbbb

     bbbbbbbbbb

dfg
     jjjjjjjjj
dfg
     jjjjjjjjj
hjk
P和p的差别,P是指打印模式空间中的第一块,而p是打印所有的

(15)、D命令:只删除模式空间中的第一行
理由同14一样
阅读(3436) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~