最近在处理一个文本,打算用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 bbbbbbbbbbdfg jjjjjjjjjhjk
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:abc2: aaaaaaaaaa3: bbbbbbbbbb4:5:dfg6: jjjjjjjjj7: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一样