我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件等等。如果我们相对这些文件进行一些编辑查询等操作时,我们可能会想到一些vi,vim,cat,more等命令。但是这些命令效率不高,这就好比一块空地准备搭建房子,请了10个师傅拿着铁锹挖地基,花了一个月的时间才挖完,而另外一块空地则请了个挖土机,三下五除二就搞定了,这就是效率。而在linux中的“挖土机”有三种型号:顶配awk,中配sed,标配grep。使用这些工具,我们能够在达到同样效果的前提下节省大量的重复性工作,提高效率。
接下来我们就看一下sed的详细说明
sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?大家可以想象以下流水线,sed就像一个车间一样,文件中的每行字符都是原料,运到sed车间,然后经过一系列的加工处理,最后从流水线下来就变成货物了。
Sed命令是操作,过滤和转换文本内容的强大工具。常用功能有增删改查(增加,删除,修改,查询),其中查询的功能中最常用的2大功能是过滤(过滤指定字符串),取行(取出指定行)。
我们现在准备学习的sed版本是GNU开源版本的,我的实验环境是CentOS6.8系统,内核版本是2.6.32-642.el6.x86_64
sed [options] [sed -commands][input -file] sed [选项] 【sed命令】 【输入文件】
文件person.txt在模式空间的完整处理流程
1,判断第1行是否是需要处理的行,如果不是要处理的行就重新从文件读取下一行,如果是要处理的行,则接着往下走。
2,对模式空间的内容执行sed命令,比如a(追加),i(插入),s(替换)...
3,将模式空间中经过sed命令处理后的内容输出到屏幕上,然后清空模式空间
4,读取下一行文本,然后重新执行上面的流程,直到文件结束
option[选项] | 解释说明(带*的为重点) |
---|---|
-n | 取消默认的sed软件的输出,常与sed命令的p连用。* |
-e | 一行命令语句可以执行多条sed命令 |
-f | 选项后面可以接sed脚本的文件名 |
-r | 使用扩展正则表达式,默认情况sed只识别基本正则表达式* |
-i | 直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件* |
[root@chensiqi1 ~]# cat >person.txt<<KOF
> 101,chensiqi,CEO
> 102,zhangyang,CTO
> 103,Alex,COO
> 104,yy,CFO
> 105,feixue,CIO
> KOF #KOF必须成对出现,表示终止输入
这里我们需要用到2个sed命令,分别是:
“a”:追加文本到指定行后,记忆方法:a的全拼是apend,意思是追加。
“i“:插入文本到指定行前,记忆方法:i的全拼是insert,意思是插入。
[root@chensiqi1 ~]
101,chensiqi,CEO
102,zhangyang,CTO106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令行详解:
2代表指定对第2行操作,其他的行忽略
i代表插入的意思,2i即在第2行前插入文本
2i后面加上空格,然后跟上你想要插入的文本即可
最后接上你想要处理的文件person.txt
双引号:把双引号的内容输出出来;如果内容中有命令,变量等,会先把命令,变量解析出结果,然后再输出最终内容来。双引号内命令或变量的写法为`命令或变量`或$(命令或变量)
单引号:所见即所得,将单引号内的内容原样输出,阻止所有字符的转义
不加引号:不会将含有空格的字符串视为一个整体输出,如果内容中有命令,变量等,会先把命令,变量解析出结果,然后再输出最终内容来,如果字符串含有空格等特殊字符,则不能完整输出,则需改加双引号。
倒引号(反引号Esc键下方):进行命令的替换,在倒引号内部的shell命令将会被执行,其结果输出代替用倒引号括起来的文本。
Sed为何用单引号?
[root@chensiqi1 ~]# cat person.txt
101,chensiqi,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO [root@chensiqi1 ~]# sed ‘2i $PATH‘ person.txt #单引号--文本内容原封不动插入
101,chensiqi,CEO $PATH
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[root@chensiqi1 ~]# sed 2i $PATH person.txt #不加引号,linux无法辨认空格,不会把有空格的命令当成一条命令来执行sed: -e expression #1, char 2: expected \ after `a‘, `c‘ or `i‘
[root@chensiqi1 ~]# sed "2i $PATH" person.txt #双引号--变量$PATH被解析以后在当作文本进行插入
101,chensiqi,CEO /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin 102,zhangyang,CTO 103,Alex,COO 104,yy,CFO 105,feixue,CIO
企业案例1:优化SSH配置(一键完成增加若干参数)
在我们学习CentOS6系统优化时,有一个优化点:更改ssh服务远程登录的配置。主要的操作是在ssh的配置文件/etc/ssh/sshd_config加入下面5行文本。(下面参数的具体含义见其他课程。)
Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GSSAPIAuthentication no
这道企业面试题可以用我们学过的sed命令多行追加功能就可以搞定。
[root@chensiqi1 ~]# sed -i ‘13i Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNS no\nGSSAPIAuthentication no‘ /etc/ssh/sshd_config
命令说明:题目要求在第13行前插入,那就需要使用命令13i。有同学做个题目时,是这样想的,在13行前,那不就是12行后吗,12a也是可以的。是的,这样也是没错的,这可以算是第二种方法。 最后插入的5行内容使用“\n”就可以变成一行了。 上面还有一个没讲过的选项"-i",这个选项能够实际的修改文件内容,大家练习时可以去掉,防止改掉了配置文件。如果使用了-i,可以用备份文件还原。当然,在生产环境修改配置文件那就需要用-i选项了。
[root@chensiqi1 ~]# sed -n ‘13,17p‘ /etc/ssh/sshd_config
Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GSSAPIAuthentication no
命令说明:查看增加的文本内容,选项-n与命令p的具体用法见后文的6.2.4查。
[root@chensiqi1 ~]# sed ‘d‘ person.txt 下面用具体的例子演示一下,测试文件还是person.txt
[root@chensiqi1 ~]#
命令说明:如果在sed命令前面不指定地址范围,那么默认会匹配所有行,然后使用d命令删除功能就会删除这个文件的所有内容
[root@chensiqi1 ~]
101,chensiqi,CEO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:这个单行删除想必大家能理解,指定删除第2行的文本102,zhangyang,CTO
[root@chensiqi1 ~]
101,chensiqi,CEO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明: 在sed软件中,使用正则的格式和awk一样,使用2个”/“包含指定的正则表达式,即“/正则表达式/”
6.2.2.2 特殊符号~(步长)解析
例子:
1~2 匹配1,3,5,7.....#-->用于只输出奇书行,大伙仔细观察一下每个数字的差值。
2~2 匹配2,4,6,8....#-->用于只输出偶数行
1~3 匹配1,4,7,10.....
2~3 匹配2,5,8,11.....
[root@chensiqi1 ~]# seq 10
1
2
3
4
5
6
7
8
9
10
命令说明:seq命令能够生成从1到10的数字序列。
[root@chensiqi1 ~]
104,yy,CFO
105,feixue,CIO
命令说明:这其实是做个加法运算,‘1,+2d’==>删除第1行到第3(1+2)行的文本。
感叹号“!”我们在很多命令里都接触过,大部分都是取反的意思,在sed中也不例外
[root@chensiqi1 ~]# sed ‘2,3!d‘ person.txt
102,zhangyang,CTO
103,Alex,COO 命令说明:
在地址范围“2,3”后面加上“!”,如果不加“!”表示删除第2行和第3行,结果如下面的例子所示
然后加上“!”的结果就是除了第2行和第3行以外的内容都删除,这个方法可以作为显示文件的第2,3行题目的补充方法。
[root@chensiqi1 ~]# sed ‘2,3d‘ person.txt 101,chensiqi,CEO104,yy,CFO105,feixue,CIO
例子:
[root@chensiqi1 ~]
101,chensiqi,CEO
106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:使用sed命令c将原来第2行“102,zhangyang,CTO”替换成“106,dandan,CSO”,整行替换
这里用到的sed命令,选项:
“s”:单独使用-->将每一行中第一处匹配的字符串进行替换==>sed命令
“g”:每一行进行全部替换-->sed命令s的替换标志之一(全局替换),非sed命令。
“-i”:修改文件内容-->sed软件的选项,注意和sed命令i区别。
sed软件替换模型
sed -i ‘s/目标内容/替换内容/g‘ chensiqi.log
sed -i ‘s#目标内容#替换内容#g‘
例子:
[root@chensiqi1 ~]
101,chensiqi,CEO
102,dandan,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:
将需要替换的文本“zhangyang”放在第一个和第二个“
[root@chensiqi1 ~]# cat >test.txt<<KOF #再新建一个简单的测试文本
> a > b > a > KOF [root@chensiqi1 ~]# cat test.txt
a b a [root@chensiqi1 ~]# x=a #->设置变量x并 赋值a
[root@chensiqi1 ~]# y=b #-> 设置变量y并赋值b
[root@chensiqi1 ~]# echo $x
a [root@chensiqi1 ~]# echo $x $y
a b 命令说明:打印变量x,y验证一下,需要使用$符号引用变量
sed软件的()的功能可以记住正则表达式的一部分,其中,\1为第一个记住的模式即第一个小括号中的匹配内容,\2第二个记住的模式,即第二个小括号中的匹配内容,sed最多可以记住9个。
例:echo "I am chensiqi teacher."如果想保留这一行的单词chensiqi,删除剩下部分,使用圆括号标记想保留的部分
[root@chensiqi1 ~]# echo "I am chensiqi teacher." | sed ‘s#^.*am \([a-z]\+\) tea.*$#\1#g‘
chensiqi [root@chensiqi1 ~]# echo "I am chensiqi teacher." | sed -r ‘s#^.*am ([a-z]+) tea.*$#\1#g‘
chensiqi [root@chensiqi1 ~]# echo "I am chensiqi teacher." | sed -r ‘s#I (.*) (.*) teacher.#\1\2#g‘
amchensiqi 命令说明: sed如果不加-r后缀,那么默认不支持扩展正则表达式,需要\符号进行转义
小括号的作用是将括号里的匹配内容进行分组以便在第2和第3个#号之间进行sed的反向引用,\1代表引用第一组,\2代表引用第二组
企业案例4:系统开机启动项优化(利用sed)
[root1 ~]# chkconfig --list | egrep -v "sshd|crond|rsyslog|sysstat|network" | awk ‘{print $1}‘ |sed -r ‘s#^(.*)#chkconfig \1 off#g‘ |bash
[root@chensiqi1 ~]# sed ‘2p‘ person.txt
101,chensiqi,CEO
102,zhangyang,CTO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令说明:选项-n取消默认输出,只输出匹配的文本,大家只需要记住使用命令p必用选项-n。 [root@chensiqi1 ~]# sed -n ‘2,3p‘ person.txt
102,zhangyang,CTO
103,Alex,COO 命令说明:查看文件的第2行到3行,使用地址范围“2,3”。取行就用sed,最简单
[root@chensiqi1 ~]# sed -n ‘/CTO/p‘ person.txt
102,zhangyang,CTO 命令说明:打印含CTO的行 [root@chensiqi1 ~]# sed -n ‘/CTO/,/CFO/p‘ person.xt
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO 命令说明:打印含CTO的行到含CFO的行。
[root@chensiqi1 ~]# sed -rn ‘/chensiqi|yy/p‘ person.txt
101,chensiqi,CEO
104,yy,CFO
命令说明:
使用扩展正则“|”,为了不使用转义符号“\”,因此使用-r选项开启扩展正则表达式模式
[root@chensiqi1 ~]# sed -n ‘1p;3p;5p‘ person.txt
101,chensiqi,CEO
103,Alex,COO
105,feixue,CIO
[root@chensiqi1 ~]# sed -n ‘2,4p;=‘ person.txt
1
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
5
命令说明:-n去掉默认输出,2,4p,输出2到4行内容,=输出全部的行的行号 [root@chensiqi1 ~]# sed -n ‘2,4{p;=}‘ person.txt
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
命令说明:‘2,4{p;=}’代表统一输出2,4行的行号和内容
原文地址:http://hujiangtao.blog.51cto.com/6123408/1923718