二、Linux三剑客之sed命令精讲

1,前言

  • 我们都知道,在Linux中一切皆文件,比如配置文件,日志文件,启动文件等等。如果我们相对这些文件进行一些编辑查询等操作时,我们可能会想到一些vi,vim,cat,more等命令。但是这些命令效率不高,这就好比一块空地准备搭建房子,请了10个师傅拿着铁锹挖地基,花了一个月的时间才挖完,而另外一块空地则请了个挖土机,三下五除二就搞定了,这就是效率。而在linux中的“挖土机”有三种型号:顶配awk,中配sed,标配grep。使用这些工具,我们能够在达到同样效果的前提下节省大量的重复性工作,提高效率。

  • 接下来我们就看一下sed的详细说明

  • sed 是Stream Editor(字符流编辑器)的缩写,简称流编辑器。什么是流?大家可以想象以下流水线,sed就像一个车间一样,文件中的每行字符都是原料,运到sed车间,然后经过一系列的加工处理,最后从流水线下来就变成货物了。

2,软件功能与版本

  • Sed命令是操作,过滤和转换文本内容的强大工具。常用功能有增删改查(增加,删除,修改,查询),其中查询的功能中最常用的2大功能是过滤(过滤指定字符串),取行(取出指定行)。

  • 我们现在准备学习的sed版本是GNU开源版本的,我的实验环境是CentOS6.8系统,内核版本是2.6.32-642.el6.x86_64

3,语法格式

sed [options] [sed -commands][input -file]
sed [选项]  【sed命令】 【输入文件】

4,命令执行流程

文件person.txt在模式空间的完整处理流程

1,判断第1行是否是需要处理的行,如果不是要处理的行就重新从文件读取下一行,如果是要处理的行,则接着往下走。
2,对模式空间的内容执行sed命令,比如a(追加),i(插入),s(替换)...
3,将模式空间中经过sed命令处理后的内容输出到屏幕上,然后清空模式空间
4,读取下一行文本,然后重新执行上面的流程,直到文件结束

5,选项说明

option[选项] 解释说明(带*的为重点)
-n 取消默认的sed软件的输出,常与sed命令的p连用。*
-e 一行命令语句可以执行多条sed命令
-f 选项后面可以接sed脚本的文件名
-r 使用扩展正则表达式,默认情况sed只识别基本正则表达式*
-i 直接修改文件内容,而不是输出到终端,如果不使用-i选项sed软件只是修改在内存中的数据,并不会影响磁盘上的文件*

不看绝对后悔的Linux三剑客之sed实战精讲_第1张图片

不看绝对后悔的Linux三剑客之sed实战精讲_第2张图片

6,使用范例

6.1 统一实验文本

[root@chensiqi1 ~]# cat >person.txt<<KOF

> 101,chensiqi,CEO

> 102,zhangyang,CTO

> 103,Alex,COO

> 104,yy,CFO

> 105,feixue,CIO

> KOF          #KOF必须成对出现,表示终止输入


6.2 常用功能-增删改查

6.2.1 增

  • 这里我们需要用到2个sed命令,分别是:
    “a”:追加文本到指定行后,记忆方法:a的全拼是apend,意思是追加。
    “i“:插入文本到指定行前,记忆方法:i的全拼是insert,意思是插入。

6.2.1.1 单行增

[root@chensiqi1 ~]# sed '2a 106,dandan,CSO' person.txt

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

6.2.1.2 引号的区别总结
  1. 双引号:把双引号的内容输出出来;如果内容中有命令,变量等,会先把命令,变量解析出结果,然后再输出最终内容来。双引号内命令或变量的写法为`命令或变量`或$(命令或变量)

  2. 单引号:所见即所得,将单引号内的内容原样输出,阻止所有字符的转义

  3. 不加引号:不会将含有空格的字符串视为一个整体输出,如果内容中有命令,变量等,会先把命令,变量解析出结果,然后再输出最终内容来,如果字符串含有空格等特殊字符,则不能完整输出,则需改加双引号。

  4. 倒引号(反引号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查。


6.2.2 删

6.2.2.1指定执行的地址范围

[root@chensiqi1 ~]# sed 'd' person.txt 下面用具体的例子演示一下,测试文件还是person.txt

[root@chensiqi1 ~]#

命令说明:如果在sed命令前面不指定地址范围,那么默认会匹配所有行,然后使用d命令删除功能就会删除这个文件的所有内容


[root@chensiqi1 ~]# sed '2d' person.txt

101,chensiqi,CEO

103,Alex,COO

104,yy,CFO

105,feixue,CIO

命令说明:这个单行删除想必大家能理解,指定删除第2行的文本102,zhangyang,CTO


[root@chensiqi1 ~]# sed '/zhangyang/d' person.txt

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命令能够生成从110的数字序列。


6.2.2.3 特殊符号+解析

[root@chensiqi1 ~]# sed '1,+2d' person.txt  

104,yy,CFO

105,feixue,CIO

命令说明:这其实是做个加法运算,‘1,+2d’==>删除第1行到第31+2)行的文本。


6.2.2.4 特殊符号!解析

感叹号“!”我们在很多命令里都接触过,大部分都是取反的意思,在sed中也不例外

[root@chensiqi1 ~]# sed '2,3!d' person.txt

102,zhangyang,CTO

103,Alex,COO 命令说明:

在地址范围“23”后面加上“!”,如果不加“!”表示删除第2行和第3行,结果如下面的例子所示

然后加上“!”的结果就是除了第2行和第3行以外的内容都删除,这个方法可以作为显示文件的第23行题目的补充方法。

[root@chensiqi1 ~]# sed '2,3d' person.txt 101,chensiqi,CEO104,yy,CFO105,feixue,CIO


6.2.3 改

6.2.3.1 按行替换

例子:

[root@chensiqi1 ~]# sed '2c 106,dandan,CSO' person.txt

101,chensiqi,CEO

106,dandan,CSO

103,Alex,COO

104,yy,CFO

105,feixue,CIO

命令说明:使用sed命令c将原来第2行“102,zhangyang,CTO”替换成“106,dandan,CSO”,整行替换

6.2.3.2 文本替换
  • 这里用到的sed命令,选项:
    “s”:单独使用-->将每一行中第一处匹配的字符串进行替换==>sed命令
    “g”:每一行进行全部替换-->sed命令s的替换标志之一(全局替换),非sed命令。
    “-i”:修改文件内容-->sed软件的选项,注意和sed命令i区别。

sed软件替换模型

sed -i 's/目标内容/替换内容/g' chensiqi.log
sed -i 's#目标内容#替换内容#g'

例子:

[root@chensiqi1 ~]# sed 's#zhangyang#dandan#g' person.txt

101,chensiqi,CEO

102,dandan,CTO

103,Alex,COO

104,yy,CFO

105,feixue,CIO

命令说明:

将需要替换的文本“zhangyang”放在第一个和第二个“#”之间

将替换后的文本“dandan”放在第二个核第三个“#”之间。结果为第二行的“zhangyang”替换为“dandan”


6.2.3.3 变量替换

[root@chensiqi1 ~]# cat >test.txt<

> 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验证一下,需要使用$符号引用变量


6.2.3.4 分组替换()和\1的使用说明

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)

[root@chensiqi1 ~]# chkconfig --list | egrep -v  "sshd|crond|rsyslog|sysstat|network" | awk '{print $1}' |sed -r 's#^(.*)#chkconfig \1 off#g' |bash


6.2.4 查

6.2.4.1 按行查询

[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行,使用地址范围“23”。取行就用sed,最简单


6.2.4.2 按字符串查询

[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的行。


6.2.4.3 过滤多个字符

[root@chensiqi1 ~]# sed -rn '/chensiqi|yy/p' person.txt

101,chensiqi,CEO

104,yy,CFO 命令说明: 使用扩展正则“|”,为了不使用转义符号“\”,因此使用-r选项开启扩展正则表达式模式


7,sed命令应用知识扩展

7.1 sed如何取不连续的行

[root@chensiqi1 ~]# sed -n '1p;3p;5p' person.txt

101,chensiqi,CEO

103,Alex,COO

105,feixue,CIO

7.2 特殊符号{}的使用

[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,输出24行内容,=输出全部的行的行号 [root@chensiqi1 ~]# sed -n '2,4{p;=}' person.txt

102,NB,CTO

2

103,Alex,COO

3

104,yy,CFO

4

命令说明:‘24{p;=}’代表统一输出24行的行号和内容