良许Linux教程网 干货合集 Linux系统三剑客-sed使用教程

Linux系统三剑客-sed使用教程

前两篇文章已经和大家分享了Linux系统三剑客awk、grep的使用教程,本篇文章和大家分享一下Linux系统三剑客随后一剑-sed的使用的方法,一起来看看把。

u=328339026,131740751&fm=26&gp=0

一.Sed简介    Sed是一款流编辑工具,用来对文本进行过滤与替换操作,特别是当你想要对几十个配置文件做统一修改时,你会感受到Sed的魅力!Sed通过一次仅读取一行内容来对某些指令进行处理后输出,所以Sed更适合于处理大数据文件。首先,Sed通过文件或管道读取文件内容,但Sed默认并不直接修改源文件,而是将读入的内容复制到缓冲区中,我们称之为模式空间(pattern space),所有的指令操作都是在模式空间中进行的,然后Sed根据相应的指令对模式空间中的内容进行处理并输出结果,默认输出至标准输出(即屏幕上)。Sed的工作流程如下图所示:

二.Sed的基本语法格式Sed从文件中读取数据,如果没有输入文件,则默认对标准输入进程数据进行处理,脚本指令是第一个非“-”开头的参数,具体语法格式如下:

sed [选项]…{脚本指令} [输入文件]选项

含义

–version

显示sed版本

–help

显示帮助文档

-n,–quit,–silent

静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,该选项可以屏蔽自动打印。

-e script

允许多个脚本指令被执行

-f script-file

从文件中读取脚本指令,对编写自动脚本程序很实用。

-i,–in-place

慎用,该选项将直接修改源文件

-l,N

该选项指令l指令可以输出的行长度,l指令为输出非打印字符。

–posix

禁用GNU sed扩展功能

-r

在脚本指令中使用扩展正则表达式

-s,–separate

默认情况下,sed将把输入的多个文件名作为一个长的连续的输入流,而GNU sed则允许把它们当作单独的文件

-u,–unbuffered

最低限度的缓存输入和输出

三.Sed入门规范1.基本格式规范

Sed通过特定的脚本指令对文件进行处理,这里就简单介绍几个脚本指令操作作为Sed程序的规范。a,append表示追加指令;i,insert表示插入指令;d,delete表示删除指令;s,substitution表示替换指令。Sed脚本指令的基本格式是:[地址]命令(有些命令仅可以对一行操作,有些可以对多行操作),命令也可以用花括号进行组合,是命令序列可以作用于同一个地址:

address{command1command2command3}注意:第一个命令可以和左花括号在同一行,但右花括号必须单独处于一行。此外,命令后添加空格会产生错误。下面的test.txt为操作样本源文件(注意有若干空白行),介绍Sed的用法:

[root@andrew Andrew]# cat -n test.txt     1 DEVICE=eno16777736     2 BOOTPROTO=static     3 IPADDR=192.168.0.1     4 NETMASK=255.255.255.0     5     6 GATEWAY=192.168.0.254     7     8 ONBOOT=yes第二行后追加TYPE=Ethernet:

[root@andrew Andrew]# sed ‘2a TYPE=Ethernet’ test.txt DEVICE=eno16777736BOOTPROTO=staticTYPE=EthernetIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=yes

第三行前追加TYPE=Network:

[root@andrew Andrew]# sed ‘3i TYPE=Network’ test.txt DEVICE=eno16777736BOOTPROTO=staticTYPE=NetworkIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=yes

将样本文件中的所有yes替换为no:

[root@andrew Andrew]# sed ‘s/yes/no/g’ test.txt DEVICE=eno16777736BOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=no

以上大多数操作指令都依据行号定位操作对象(地址),如2a即第二行后追加。实际工作中,可能大多数情况你并不确定你要操作对象(地址)的行号,这时更多的会使用正则表达式确定操作对象(地址)。下面是使用正则表达式定位操作行的示例:

匹配到包含ONBOOT的行,并在其后添加TYPE=Ethernet:

[root@andrew Andrew]# sed ‘/ONBOOT/a TYPE=Ethernet’ test.txt DEVICE=eno16777736BOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=yesTYPE=Ethernet

匹配GATEWAY开始的行,并删除该行:

[root@andrew Andrew]# sed ‘/^GATEWAY/d’ test.txt DEVICE=eno16777736BOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0

ONBOOT=yes

另外,我们的操作指令可以写入到脚本文件中,并通过sed的-f选项读取,脚本文件中的注释行是以#开始的行,如果#后面的字符为n,则屏蔽Sed程序的自动输出功能,等同于命令选项-n。创建一个sed脚本,内容如下:

[root@andrew Andrew]# cat sed.sh#This is a test sed command#脚本内容为匹配到空白行后,删除该行/^$/d对test.txt文件执行sed.sh脚本指令:

[root@andrew Andrew]# sed -f sed.sh test.txt DEVICE=eno16777736BOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254ONBOOT=yes

而当你需要执行多个指令时,可以使用以下三种方法:

(1)使用分号隔开指令

[root@andrew Andrew]# sed ‘s/yes/no/;s/static/dhcp/’ test.txt DEVICE=eno16777736BOOTPROTO=dhcpIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=no

(2)使用-e选项

[root@andrew Andrew]# sed -e ‘s/yes/no/’ -e ‘s/static/dhcp/’ test.txt DEVICE=eno16777736BOOTPROTO=dhcpIPADDR=192.168.0.1NETMASK=255.255.255.0

GATEWAY=192.168.0.254

ONBOOT=no

(3)利用分行

[root@andrew Andrew]# sed ‘

s/yes/no/s/static/dhcp/’ test.txtDEVICE=eno16777736BOOTPROTO=dhcpIPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254ONBOOT=no

然而在命令行上输入过长的指令是愚蠢的,这时需要使用-f选项指定sed脚本文件,在脚本文件中可以包含多行指令,而且也便于修改。

2.操作地址匹配范例

通过以上范例不难发现,我们编写的脚本指令需要指定一个地址来决定操作范围,如果不指定,则默认对文件的所有行进行操作。如:sed ‘d’ test.txt将删除test.txt的所有行,而‘2d’则仅删除第二行。Sed为我们提供了以下这些方式来确定需要操作地址的范围。

-number

指定输入文件的唯一行号

-first~step

指定以first开始,并指定操作步长为step,如1、2指定第一行、第三行、第五行……为操作地址。2~5指定第二行开始,每5行匹配一次操作地址

$

匹配文件的最后一行

/regexp/

//中间包含的是正则表达式,通过正则表达式匹配操作地址。如果//中正则表达式为空,匹配最近一次正则表达式的匹配地址,后面会有范例

\cregexpc

\c和c之间匹配正则表达式,c字符可以使用任意字符代替

addr1,addr2

匹配从操作地址1到操作地址2的所有行

addr1,+N

匹配地址1以及后面的N行内容

打印文件的奇数行:

[root@andrew Andrew]# cat -n test.txt     1 DEVICE=eno16777736     2 BOOTPROTO=static     3 IPADDR=192.168.0.1     4 NETMASK=255.255.255.0     5     6 GATEWAY=192.168.0.254     7     8 ONBOOT=yes[root@andrew Andrew]# sed -n ‘1~2p’ test.txt DEVICE=eno16777736IPADDR=192.168.0.1

删除2~8之间的所有行:

[root@andrew Andrew]# cat -n test.txt     1 DEVICE=eno16777736     2 BOOTPROTO=static     3 IPADDR=192.168.0.1     4 NETMASK=255.255.255.0     5     6 GATEWAY=192.168.0.254     7     8 ONBOOT=yes[root@andrew Andrew]# sed ‘2,8d’ test.txt DEVICE=eno16777736

四.Sed指令和脚本1.Sed常用指令汇总

下表给出了常用sed脚本指令的说明,下面分别看看每个指令的详细用法:

指令

功能

指令

功能

-s

替换

-d

删除

-a

追加

-i

插入

-c

更改

-l

打印(显示非打印字符)

-y

按字符转换

-L

打印(不显示非打印字符)

-p

打印

-r

读入文件内容

-w

保存至文件

-q

退出

2.部分指令详解

(1)替换指令(s,Substitution)

指令格式:[address]s/pattern/replacement/flags

address为操作地址,s为替换指令,/pattern/匹配需要替换的内容,/replacement为替换的新内容。Flags标记可以是:

Flags标记

含义

-n

1-512之间的数字,表示对模式空间中指定模式的第n次出现进行替换。如一行中有3个A,而只想替换第二个A。

-g

对模式空间的所有匹配进行全局更改。没有g则只有第一次匹配被替换,如一行中有3个A,则仅替换第一个A。

-p

打印模式空间的内容

-w file

将模式空间的内容写到文件file中

replacement为字符串,用来替换与正则表达式匹配的内容。在replace部分,只有下列字符有特殊含义:

&

用正则表达式匹配的内容进行替换

\n

匹配第n个子串,该子串之前在pattern中用\(\)指定

\

转义(转义替换部分包含:&、\等)

(2)删除指令(d,delete)

删除指令用于删除匹配的行,而且删除命令还会改变sed脚本中命令的执行顺序。因为匹配的行一旦删除,模式空间将变为“空”,自然不会再执行sed脚本后续的命令。删除命令将导致读取新的输入行(下一行),而sed脚本中的命令则从头开始重新执行。需要注意的是,删除时是删除整行,而不只是删除匹配的内容(如果删除匹配的内容,可以使用替换)

(3)转换指令(y)

按字符转换(Transform)的语法格式为:[address]y/source-chars/dest-chars,其中,[address]用来定位需要修改的行,source-chars为需要被修改的字符,dest-chars为准备替换的字符。

3.Sed脚本指令范例

(1)范例1

范例1所使用的样本文件为:

[root@andrew Andrew]# cat test.txt

Hello the World!

范例1:将样本文件中第二个替换为

编写sed脚本,替换与行匹配相同的内容,即将body替换为/body,但仅替换第二个body为/body。

[root@andrew Andrew]# cat sed.sh /body/{s//\/body/2}

执行sed程序的结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt

Hello the World!

(2)范例2

范例2使用的样本文件为:

[root@andrew Andrew]# cat test.txt

h1Helloh1h2Helloh2h3Helloh3

范例2:给所有第一个的h1,h2等添加,第二个h1,h2添加>.

编写sed脚本为:

[root@andrew Andrew]# cat sed.sh /h[0-9]/{s//&>/1s//\/&>/2}

说明:匹配h紧跟一个数字的行,替换与上一行中匹配内容相同的内容,即将h[0-9]替换为,其中&为前面要替换的内容。第一条s替换指令仅替换第一个h1,h2…,第二条s替换指令用来替换第二个h1,h2…

执行sedc程序的结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt

Hello

Hello

Hello

技巧:关于‘s///’命令的另一个妙处是:‘/’分隔符有许多替换方案,如果规则表达式或替换字符串中有许多斜杠,则可以通过在‘s’之后指定一个不同的字符来更改分隔符。示例:sed -e ‘s:/usr/local:/usr:g’ mylist.txt此时是替换分隔符,sed会将/usr/local替换为/usr.

(3)范例3

范例3所使用的样本文件为(注意有空白行):

[root@andrew Andrew]# cat test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=static

IPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254

范例3:删除文件中的空白行。

编写sed脚本为:

[root@andrew Andrew]# cat sed.sh /.*/{/^$/d}

执行sed程序的结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254

(4)范例4-范例6

范例4-范例7所使用的样本文件为:

[root@andrew Andrew]# cat test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticNETMASK=255.255.255.0GATEWAY=192.168.0.254

范例4:在static行后添加一行,内容为IPADDR=192.168.0.1。

[root@andrew Andrew]# sed ‘/static/a IPADDR=192.168.0.1’ test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254

范例5:在匹配NETMASK的行前插入内容IPADDR=192.168.0.1。

[root@andrew Andrew]# sed ‘/NETMASK/i IPADDR=192.168.0.1’ test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticIPADDR=192.168.0.1NETMASK=255.255.255.0GATEWAY=192.168.0.254

范例6:将包含ONBOOT行的内容更改为ONBOOT=no

[root@andrew Andrew]# sed ‘/ONBOOT/c ONBOOT=no’ test.txt DEVICE=eno16777736ONBOOT=noBOOTPROTO=staticNETMASK=255.255.255.0GATEWAY=192.168.0.254

(5)范例7和范例8

范例7和范例8所使用的样本文件为:

[root@andrew Andrew]# cat test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticnetmask=255.255.255.0GATEWAY=192.168.0.254

范例7:将小写转换为大写

编写sed脚本为:

[root@andrew Andrew]# cat sed.sh /.*/{/netmask/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/}

执行sed程序的结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt DEVICE=eno16777736ONBOOT=yesBOOTPROTO=staticNETMASK=255.255.255.0GATEWAY=192.168.0.254

范例8:显示第一、第二行的内容

打印(p):作用类似于l(列印),但不显示非显示字符,一般与-n配合使用

[root@andrew Andrew]# sed -n ‘1,2p’ test.txt DEVICE=eno16777736ONBOOT=yes

(6)范例9和范例10

范例9和范例10所使用的样本文件为:

[root@andrew Andrew]# cat name.txt JacobTomJerry[root@andrew Andrew]# cat mail.txt jacob@gmail.comtom@gmail.comjerry@gmail.com

范例9:先读取name.txt文件内容,再读取mail.txt文件内容。

编写sed脚本为:

[root@andrew Andrew]# cat sed.sh /.*/{$r mail.txt}

执行sed程序的结果如下:

[root@andrew Andrew]# sed -f sed.sh name.txt JacobTomJerryjacob@gmail.comtom@gmail.comjerry@gmail.com

范例10:显示name.txt内容的前两行内容后退出sed指令。

[root@andrew Andrew]# sed ‘2q’ name.txt JacobTom

五.Sed高级应用正常的Sed数据处理流程是读取文档的一行至模式空间,然后对该行应用相应的Sed指令,当指令完成后输出该行并清空模式空间,依次循环读入文档的下一行数据,直至文档数据结尾。然而在真实环境中的数据可能不会那么有规律,有时我们会把数据分多行写入文档,如:

姓名:张三,邮箱:zhangsan@gmail.com姓名:李四,邮箱:lisi@gmain.com从上面的模板文件中可以看出,实际上每两行为一条完整的记录,而此时如果需要使用Sed对该文档进行处理,就需要对Sed工作流程进行人工干预。

1.多行操作Next

Next(N)指令通过读取新的输入行,并将它追加至模式空间的现有内容之后,来创建多行模式空间。模式空间的最初内容与新的输入行之间用换行符分割。在模式空间中插入的换行符可以使用\n匹配。

范例1:使用的样本文件为:

[root@andrew Andrew]# cat test.txt Name:TomMail:Tom@gmail.comName:JerryMail:Jerry@gmail.com编写Sed指令脚本如下(读取样本文件内容至模式空间,当读取的内容与Name匹配时,立刻读取下一行内容,再输出模式空间中的内容,#n用来屏蔽自动输出)。

[root@andrew Andrew]# cat sed.sh #n/Name/{NL}

运行脚本结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt Name:Tom Mail:Tom@gmail.comName:Jerry Mail:Jerry@gmail.com

范例2:使用的样本文件为:

[root@andrew Andrew]# cat test.txt 111222222222333

编写Sed指令脚本(读取样本文件内容至模式空间,当读取的内容与222匹配时,立刻读取下一行内容,再输出模式空间中的内容,小写的l会打印非打印字符)。

[root@andrew Andrew]# cat sed.sh #n/222/{Nl}运行脚本结果如下:

[root@andrew Andrew]# sed -f sed.sh test.txt 222\n222

2.多行操作Print

Print(P)即多行打印P,它与打印p稍有不同,前者仅输出多行模式空间中的第一部分,直到第一个插入的\n换行符为止。综合范例所使用的样本文件为:

[root@andrew Andrew]# cat test.txt aaabbbcccdddeeefff下面通过多条sed命令对比不同打印方式的差别,输出结果如下所示:

[root@andrew Andrew]# sed ‘/.*/N’ test.txt aaabbbcccdddeeefff

[root@andrew Andrew]# sed ‘/.*/N;L’ test.txt aaa bbbaaabbbccc dddcccdddeee fffeeefff

[root@andrew Andrew]# sed ‘/.*/N;P’ test.txt aaaaaabbbccccccdddeeeeeefff

[root@andrew Andrew]# sed ‘/.*/N;p’ test.txt aaabbbaaabbbcccdddcccdddeeefffeeefff第一个sed命令使用了N读取下一行,新读取的内容与原有内容直接使用\n分隔。但sed读取下一行后没有任何后续指令,所以sed自动输出,即输出源文件的所有内容。

第二个sed命令使用了N读取下一行,L表示显示模式空间的内容,即aaa bbb,同时sed命令的自动输出功能会把源文件内容显示出来,即aaa,bbb。以此类推,sed继续读取第三行ccc,并使用N将ddd追加至行尾,使用L显示模式空间的内容(不显示非打印字符),sed自动输出后再把源文件内容显示出来。

第三个sed命令使用N将下一行追加至行尾,现在模式空间中的内容为aaa\bbb,而P指令的作用是打印模式空间中的第一部分内容直到\n结尾,即仅打印aaa,这时sed的自动输出功能输出aaa,bbb(sed自动输出会将\n输出为换行)。依次类推,读取第三行ccc,N将ddd追加至行尾,P打印\n前的内容,同时sed命令也将自动输出。

第四个sed命令的原理类似于第三个sed命令,但p打印时,\n看作回车换行,所以打印出来的是aaa回车bbb.

3.多行删除操作Delete(D)

指令d为删除命令,其作用是删除模式空间中的内容并读入新的输入行,而如果sed在d指令后还有多条指令,则余下的指令将不再执行,而是返回第一条指令对新读入行进行处理。而多行删除指令D将删除模式空间中直到第一个插入的换行符(\n)前的这部份内容,它不会读入新的输入行,并返回sed脚本的顶端,使得剩余指令继续应用于模式空间中剩余的内容。

4.Hold(h,H),Get(g,G)

我们知道,模式空间是存放当前输入行的缓冲区。除此之外,Sed还有一个称为保持空间(hold space)的缓冲区。模式空间的内容可以复制到保持空间,保持空间的内容同样可以复制到模式空间,有一组Sed命令用于在两者之间移动数据。

Hold(h|H)

将模式空间的内容复制或追加到保持空间

Get(g|G)

将保持空间的内容复制或追加到模式空间

Exchange(x)

交换保持空间与模式空间的内容

保留空间范例所使用的样本文件如下:

[root@andrew Andrew]# cat test.txt aaabbbcccddd[root@andrew Andrew]# cat sed.sh /aaa/{hd}/ccc/{G}[root@andrew Andrew]# sed -f sed.sh test.txt bbbcccaaaddd

至此关于Linux系统三剑客的最后一剑sed分享结束,欢迎大家在评论区留言。

以上就是良许教程网为各位朋友分享的Linux系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你!

137e00002230ad9f26e78-265x300

本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部