zl程序教程

您现在的位置是:首页 >  系统

当前栏目

L29.linux命令每日一练 -- 第四章 文本处理三剑客 -- sed命令

Linux命令 -- 每日 sed 第四章 三剑客 文本处理
2023-09-14 09:09:06 时间

4.2 sed:流编辑器

4.2.1 sed命令语法及参数说明

【命令星级】 ★★★★★

【功能说明】

​ sed是Stream Editor(字符流编辑器)的缩写,简称流编辑器。它是Linux三剑客之一。

​ sed是操作、过滤和转换文本内容的强大工具。sed的常用功能包含对文件实现快速增删改查(增加、删除、修改、查询),其中查询的功能中最常用的两大功能是过滤(过滤指定字符串)和取行(取出指定的行)。

【语法格式】

sed [选项] [sed内置命令字符] [输入文件]

说明:

​ 1)为了避免混淆,本文称呼sed为sed或sed命令,将实现不同sed功能的内部命令参数,称为“sed内置命令字符”,以区别是sed命令还是sed内置命令选项。

​ 2)“sed内置命令字符”既可以是单个命令,也可以是多个命令参数的组合。

​ 3)“输入文件”为sed需要处理的文件,是可选项,sed还能从标准输入(如管道)获取输入。

【选项说明】

​ 表4-2针对sed命令的参数选项进行了说明。

​ 表4-2 sed常用参数选项
在这里插入图片描述
sed内置命令字符可用来实现对文件的不同操作功能,例如对文件的增删改查等,表4-3为sed的内置命令字符说明。

​ 表4-3 sed的常用内置命令字符功能说明

在这里插入图片描述

4.2.2 使用范例

4.2.2.1 基础范例

​ 为了更好地测试sed命令的用法,准备测试的内容及文件如下:

[root@centos7 ~]# cat >persons.txt<<EOF
> 101,netealge,CEO
> 102,zhangyao,CTO
> 103,Alex,COO
> 104,yy,CFO
> 105,feixue,CIO
> EOF	#这里要敲回车才能结束,另外,EOF必须成对出现,但也可以用别的成对标签来替换。例如:neteagle字符标签。

​ **范例4-10:**在文件指定行后追加文本。

[root@centos7 ~]# sed '2a 106,dandan,CSO' persons.txt 	#这里使用了sed内置命令a追加功能。
101,netealge,CEO
102,zhangyao,CTO
106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CIO

命令详细说明:

​ 首先我们来看一下命令执行后的结果,可以看到在第二行"102,zhangyao,CTO"后面追加了一行新的文本“106,dandan,CSO”。

​ 接下来我们解读一下该sed命令语句的结构,sed开头,然后接上空格,这里要郑重地和大家说一点,在练习Linux命令时一定不要忘了空格(空格个数不限,但至少要有一个!),Linux命令和各个参数之间都需要以空格作为分隔符,否则命令会无法执行。

​ 在空格后面,我们先输入一对单引号(‘’),然后再退一格在单引号中输入sed的内置命令字符,先把2个引号输入完了再在里面填写内容,这也是一格良好的习惯,因为很多人在输入内容的时候把后面的引号忘了,最后命令执行失败还不知道哪里错了,因此我们要养成良好的习惯,以避免没有意义的错误。

​ 接下来所讲的是重点了,新手们,一定要记好!

  • sed后面单引号中的内容为:2a 106,dandan,CSO。

  • 2表示对第2行进行操作,其他的行忽略。

  • a表示追加,2a即在第2行后追加文本。

  • 2a后面加上空格,然后接着输入想要追加的文本内容(106,dandan,CSO)即可。

    ​ **范例4-11:**在文件指定的行前加入文本。

    [root@centos7 ~]# sed '2i 106,dandan,CSO' persons.txt 	#这里使用了sed内置命令i插入功能。
    101,netealge,CEO
    106,dandan,CSO
    102,zhangyao,CTO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    

命令详细说明:

​ 首先我们来看一下上述命令的执行结果,可以看到命令执行后在原来的第二行"102,zhangyao,CTO"前面插入了新的一行为“106,dandan,CSO”,原来的第2行变成了第3行了。

​ 接下来我们解读一下该sed命令语句的结构,以sed开头,然后接上空格,在空格后面,是一对单引号(‘’),然后再单引号中的内容是“2i 106,dandan,CSO”。

  • 2表示对第2行进行操作,其他的行可忽略。

  • i代表插入的意思,2i表示在第2行即当前行插入文本,即插入到第二行。

  • 2i后面加上空格,然后跟上要插入的文本(106,dandan,CSO),最后接上要处理的文件persons.txt。

    ​ **范例4-12:**在文件指定行后追加多行文本。

    [root@centos7 ~]# sed '2a 106,dandan,CSO\n107,bingbing,CCO' persons.txt 
    101,netealge,CEO
    102,zhangyao,CTO
    106,dandan,CSO
    107,bingbing,CCO
    103,Alex,COO
    104,yy,CFO
    105,feixue,CIO
    

    命令详细说明:

    ​ 首先我们粗略看一下该命令语句,可以发现命令结构与单行增加文本几乎是没有区别的。

    ​ 然后我们看一下命令的结果,可以看到原来的第二行“102,zhangyao,CTO”后面追加了2行文本“106,dandan,CSO”和“107,bingbing,CCO”。

    ​ 接下来我们解读一下该sed命令语句的结构,sed软件大头,然后接上空格,在空格后面,我们先输入一对单引号(‘’),然后退一格在单引号中的内容是’2a 106,dandan,CSO\n107,bingbing,CCO’。

  • 2代表指定对第2行进行操作,其他的行忽略。

  • a代表追加的意思,2a即在第2行后追加文本。

  • 2a后面加上空格,然后输入想要插入的多行文本即可。这里的每行文本都使用“\n”连接就可以写成一行了。最后输入想要处理的文件persons.txt

​ 同理,在文件指定行前插入多行文本只需要将本例的sed内置命令a换成i就可以了。

​ **范例4-13:**删除文件中一行指定的文本。

[root@centos7 ~]# sed '2d' persons.txt 	#这里使用了sed内置命令d实现删除功能,指定删除第2行的文本。
101,netealge,CEO
103,Alex,COO
104,yy,CFO
105,feixue,CIO

​ **范例4-14:**删除文件中指定的多行文本。

[root@centos7 ~]# sed '2,5d' persons.txt 	#“2,5”是一个数字地址的组合,用逗号作为分隔,其作用是删除文件的第二行到第五行(删除多行)文本,包括第2行和第5行,因此只剩下第1行。
101,netealge,CEO

​ **范例4-15:**使用sed命令替换文本内容。

[root@centos7 ~]# sed 's#zhangyao#dandan#g' persons.txt 	#这里使用了sed内置命令s来实现替换功能,并且使用了全局替换标志g表示替换文件中匹配zhangyao的所有字符串。需要注意一下语法格式,将需要替换的文本“zhangyao”放在第一个和第二个“#”之间,将替换后的文本“dandan”放在第二个和第三个“#”之间。结果为第二行的“zhangyao”替换为“dandan”。
101,netealge,CEO
102,dandan,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO

​ **范例4-16:**打印输出文件的指定行的内容。

[root@centos7 ~]# sed '2p' persons.txt 	#这里使用了sed内置命令p实现查询功能,并结合数字地址指定查询第2行的内容,但是我们会发现结果不只是输出第2行,文件的其他内容也显示出来了,这是因为sed命令有一个默认输出的功能。
101,netealge,CEO	#默认输出的行。
102,zhangyao,CTO	#p命令输出的行。
102,zhangyao,CTO	#默认输出的行。
103,Alex,COO	#默认输出的行。
104,yy,CFO	#默认输出的行。
105,feixue,CIO	#默认输出的行。
[root@centos7 ~]# sed -n '2p' persons.txt 	#为了解决上面命令显示多余内容的问题,使用选项-n取消默认输出,只输出匹配行的文本,因此大家只需要记住使用命令p必用选项-n。
102,zhangyao,CTO
[root@centos7 ~]# sed -n '2,3p' persons.txt 	#当然使用地址范围“2,3”能够查看第2行到第3行的内容。
102,zhangyao,CTO
103,Alex,COO

4.2.2.2 生产案例

​ **范例4-17:**优化SSH配置(在SSH服务的配置文件中增加多行参数)。

​ 在学习CentOS系统的优化时,有一个优化点:更改ssh服务远程登录的配置。主要的操作是在ssh的配置文件/etc/ssh/sshd_config中加入下面5行文本。

Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GssAPIAuthentication no

​ 当然我们可以使用vi/vim命令编辑这个文本,但这样会比较麻烦,现在想用一条命令增加上述5行文本到第13行前。

​ **注意:**修改前别忘了备份配置文件:cp /etc/ssh/sshd_config{,.ori}。

[root@centos7 ~]# sed -i.bak '13i Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNS no\nGssAPIAuthentication no' /etc/ssh/sshd_config 	#这道题用到了范例4-3的方法,将插入的5行内容使用“\n”就可以变成一行了。题目要求在第13行前面插入,因此这里使用sed内置命令i。i后面接字符,表示备份文件后再处理,例如:-i.bak,是先把/etc/ssh/sshd_config文件备份为/etc/ssh/sshd_config.bak后,再处理文件。

​ 上面执行的命令出现了一个新的选项“-i”,这个选项的作用是能够实际修改文件的内容,可能读者也发现了前面几个例子操作完命令之后,文件的内容并没有发生变化,这是因为sed命令默认操作的是内存中的数据,如果想要真正地修改文件的内容,就需要使用选项“ -i”将修改写到磁盘文件上。

[root@centos7 ~]# sed -n '13,17p' /etc/ssh/sshd_config		#查看文件的第13行到第17行,确认修改成功。
Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GssAPIAuthentication no

[root@centos7 ~]# rm -f /etc/ssh/sshd_config
[root@centos7 ~]# mv /etc/ssh/sshd_config.bak /etc/ssh/sshd_config

​ **范例4-18:**通过Shell脚本生成的账号密码如下所示。

[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 	#生成8位随机数。
BhmksfZA[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
jP2sJu5s[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
APE6F0e6[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
ziYCdEBq[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
5hHUFlQ8[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
LfP8L5fa[root@centos7 ~]# cat /dev/urandom | tr -dc '[:alnum:]' | head -c8 
Pqk8nA89[root@centos7 ~]# cat >test.txt<<EOF	#创建测试文件。
> stu10309
> BhmksfZA
> stu10312
> jP2sJu5s
> stu10315
> APE6F0e6
> stu10318
> ziYCdEBq
> sut10321
> 5hHUFlQ8
> stu10324
> LfP8L5fa
> stu10327
> Pqk8nA89
> EOF
[root@centos7 ~]# cat test.txt 
stu10309	#账号。
BhmksfZA	#密码。
stu10312
jP2sJu5s
stu10315
APE6F0e6
stu10318
ziYCdEBq
sut10321
5hHUFlQ8
stu10324
LfP8L5fa
stu10327
Pqk8nA89

​ 现在要求使用命令将上面的文本转换成下面SVN服务配置文件中的账号及密码格式。

stu10309=BhmksfZA	#格式“账号=密码”。
stu10312=jP2sJu5s
stu10315=APE6F0e6
stu10318=ziYCdEBq
sut10321=5hHUFlQ8
stu10324=LfP8L5fa
stu10327=Pqk8nA89

​ **提示:**实现的思路就是将奇数行和偶数行用“=”(等号)连接成一行。

​ 解答:此题利用了sed的特殊功能应用。

[root@centos7 ~]# sed 'N;s#\n#=#g' test.txt 
stu10309=BhmksfZA
stu10312=jP2sJu5s
stu10315=APE6F0e6
stu10318=ziYCdEBq
sut10321=5hHUFlQ8
stu10324=LfP8L5fa
stu10327=Pqk8nA89

命令详细说明:

​ sed内置命令N的作用:不会清空模式空间内容,并且从输入文件中读取下一行数据,追加到模式空间中,两行数据以换行符\n连接。

​ 第一行是“stu10309”存入模式空间,碰到命令“N”,读取第二行“BhmksfZA”,此时模式空间内容为“stu10309\nBhmksfZA”;然后执行“s#\n#=#g”将“\n”替换为“=”,即为“stu10309=BhmksfZA”,输出到平面上,第一个循环结束;后面的循环和前面的思路一样,直到文件结束,更多细节请参考本书sed命令部分。