Shell命令——sed命令
创始人
2024-05-29 08:48:58
0

以下内容整理于《linux命令行与shell脚本编程大全【第三版】》一书。

一、简介sed编辑器

1、sed编辑器的本质

sed是stream editor的缩写,中文意思是“流编辑器”。

sed编辑器是一个命令行编辑器,也就是可以在命令行上完成数据的处理(替换、删除、插入、修改、转换等操作)。

sed编辑器本质是一个Shell外部命令,因此也叫sed命令,通过该命令可以基于某些规则来编辑数据流。

2、sed编辑器的使用 

在命令行上使用sed命令的格式如下:

sed option script file

(1)file表示要处理哪个文本文件,如果没有明确指出,则默认从标准输入流获得内容。

(2)script表示编辑器命令,也就是对file进行哪些操作。

  • 这些编辑器命令可以直接写在命令行上,也可以写在一个文件中。
  • 如果编辑器命令中有空格,则必须用单引号包围起来。
  • 直接写在命令行时,如果有多条命令,则命令之间以分号隔开,此时option要写为-e。
  • 写在一个文件中时,如果有多条命令,则一行写一条命令即可,末尾不需要分号,此时option要写成-f。

(3)optiton的可选项包括-e、-f和-n。

  • -e表示在命令行上有多条编辑器命令。
  • -f表示编辑器命令写在一个文件中。
  • -n表示禁止sed编辑器输出。

(4)sed编辑器并不会修改文本文件的内容,它只会将修改后的数据发送到标准输出,原来的文本文件依然保留着原始的数据。

  • sed编辑器一次从输入(文件或者标准输入流)中获取一行的数据。
  • 根据所提供的编辑器命令script匹配数据。
  • 按照编辑器命令修改数据流中的数据。
  • 将修改后的数据输出到标准输出中。

(5)以sed编辑器命令中的文本替换命令s为例,说明上述的内容。

xjh@ubuntu:~/iot/tmp$ cat data1.txt #data1.txt文件内容
This is a test
xjh@ubuntu:~/iot/tmp$ sed 's/test/big test/' data1.txt #从文件中获取要处理的数据
This is a big test
xjh@ubuntu:~/iot/tmp$ sed -n 's/test/big test/' data1.txt #添加-n选项后没有内容输出
xjh@ubuntu:~/iot/tmp$
xjh@ubuntu:~/iot/tmp$ sed -e 's/test/big test/;s/This/It/' data1.txt #在命令行输入多条编辑命令,用分号隔开,添加-e选项
It is a big test
xjh@ubuntu:~/iot/tmp$ sed 's/test/big test/;s/This/It/' data1.txt #没有-e选项也可以?
It is a big test
xjh@ubuntu:~/iot/tmp$ sed 's/XJH/XJQ/' #这里没有给出要处理的内容,所以默认从标准输入获取,因此接下来要键入内容
XJH is very handsome #输入内容
XJQ is very handsome #显示处理后的内容
My name is XJH       #如果没有输入ctrl+d产生EOF字符,则会要求一直输入,并一直输入
My name is XJQ
xjh@ubuntu:~/iot/tmp$ cat script.sed #编辑器命令写在一个文件中,后缀.sed只是为区分shell脚本,非必需
s/XJH/XJQ/
s/handsome/beautiful/
s/boy/girl/
xjh@ubuntu:~/iot/tmp$ cat data2.txt 
XJH is very handsome
XJH is a handsome boy
xjh@ubuntu:~/iot/tmp$ sed -f script.sed data2.txt #编辑器命令写在一个文件中,需添加-f选项
XJQ is very beautiful
XJQ is a beautiful girl
xjh@ubuntu:~/iot/tmp$ cat  data2.txt  #sed编辑器不会修改文本文件的内容,原来的文本文件依然保留着原始的数据。
XJH is very handsome
XJH is a handsome boy
xjh@ubuntu:~/iot/tmp$ sed script.sed data2.txt 
sed: -e expression #1, char 10: unterminated `s' command
xjh@ubuntu:~/iot/tmp$ sed -nf script.sed data2.txt 
xjh@ubuntu:~/iot/tmp$ sed -n -f script.sed data2.txt 
xjh@ubuntu:~/iot/tmp$ 

二、sed编辑器的命令

sed编辑器定义了很多类型的命令,比如文本替换命令s、删除命令d、插入命令i、修改命令c、转换命令y、写入命令w等命令, 这些命令可以满足不同的编辑需求。

1、文本替换命令s

上面的例子是文本替换命令s的简单情形,接下来讲解其复杂一些的情形。

(1)可以将字符串分隔符修改为其他字符。

xjh@ubuntu:~/iot/tmp$ cat data1.txt 
This is a test
xjh@ubuntu:~/iot/tmp$ sed 's/test/big test/' data1.txt 
This is a big test
xjh@ubuntu:~/iot/tmp$ sed 's:test:big test:' data1.txt
This is a big test
xjh@ubuntu:~/iot/tmp$ sed 's!test!big test!' data1.txt
This is a big test
xjh@ubuntu:~/iot/tmp$

(2)可以选用替换标志来控制替换的方式。格式如下:

s/pattern/replacement/flags
  • 数字,表示替换第几处模式匹配的地方。
  • g,表示新文本将替换所有匹配的文本。
  • p,表示打印与模式匹配的行的原先内容。
  • w file,表示将替换的结果写到文件file中。
xjh@ubuntu:~/iot/tmp$ cat data3.txt
This is a test of the test script.
This is the second test of the test script.
xjh@ubuntu:~/iot/tmp$ sed 's/test/trial/' data3.txt  #默认替换每行中第一处匹配
This is a trial of the test script.
This is the second trial of the test script.
xjh@ubuntu:~/iot/tmp$ sed 's/test/trial/2' data3.txt #使用数字,指定替换每行中第几处匹配
This is a test of the trial script.
This is the second test of the trial script.
xjh@ubuntu:~/iot/tmp$ sed 's/test/trial/g' data3.txt #使用g,指定替换每行中所有的匹配
This is a trial of the trial script.
This is the second trial of the trial script.
xjh@ubuntu:~/iot/tmp$ sed 's/test/trial/p' data3.txt #使用p,表示如果匹配,则在输出替换后的内容之前,先输出原先行的内容
This is a trial of the test script.
This is a trial of the test script.
This is the second trial of the test script.
This is the second trial of the test script.
xjh@ubuntu:~/iot/tmp$ sed -n 's/test/trial/p' data3.txt #-n选项表示禁止sed输出,
This is a trial of the test script.                     #但p标志会输出修改后的行,二者结合表示输出替换后的内容
This is the second trial of the test script.
xjh@ubuntu:~/iot/tmp$ sed 's/test/trial/w test.txt' data3.txt #使用w,指定将替换后的结果输出到文件中
This is a trial of the test script.
This is the second trial of the test script.
xjh@ubuntu:~/iot/tmp$ cat test.txt 
This is a trial of the test script.
This is the second trial of the test script.
xjh@ubuntu:~/iot/tmp$ 

(3)通过行寻址,可以让编辑器命令只作用于文本文件的某些特定的行。在sed编辑器中可以用数字来表示特定的行或者行区间,或者可以用文本模式过滤出特定的行。注意,下面的例子都是以s命令为例进行说明的,但其实其他命令也适用。

【1】以数字来表示特定的行或者行区间,使用格式如下。

sed '起始行号,结束行号s/pattern/replacement/' file

如果有多条命令,则使用{ }将多条(以分号隔开,或者用次提示符的方式)的命令包围起来。

注意,sed编辑器将文本流中的第一行编号为1,文本流最后一行用$来表示。 

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
XJH is a boy.
XJH is a boy.
XJH is a boy.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$ sed '2s/boy/girl/' data4.txt #替换第2行
XJH is a boy.
XJH is a girl.
XJH is a boy.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$ sed '2 s/boy/girl/' data4.txt #有空格也行
XJH is a boy.
XJH is a girl.
XJH is a boy.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$ sed '2,3s/boy/girl/' data4.txt #标准例子
XJH is a boy.
XJH is a girl.
XJH is a girl.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$ sed '2,$s/boy/girl/' data4.txt #符号$表示文本最后一行
XJH is a boy.
XJH is a girl.
XJH is a girl.
XJH is a girl.
xjh@ubuntu:~/iot/tmp$ sed '2,3{s/boy/girl/;s/XJH/XJQ/}' data4.txt #多条命令的写法1
XJH is a boy.
XJQ is a girl.
XJQ is a girl.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$ sed '2,3{s/boy/girl/ 
> s/XJH/XJQ/
> }' data4.txt
XJH is a boy.                                  #多条命令的写法2
XJQ is a girl.
XJQ is a girl.
XJH is a boy.
xjh@ubuntu:~/iot/tmp$

 【2】用文本模式过滤出特定的行,使用格式如下。

sed '/pattern/s/pattern_s/replacement/' file

如果有多条命令,则使用{ }将多条(以分号隔开,或者用次提示符的方式)的命令包围起来。  

xjh@ubuntu:~/iot/tmp$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
xjh@ubuntu:~/iot/tmp$ sed -n '/root/s/bash/sh/p' /etc/passwd #添加-n选项与替换标志p,只打印替换后的行内容
root:x:0:0:root:/root:/bin/sh
xjh@ubuntu:~/iot/tmp$ sed '/root/s/bash/sh/' /etc/passwd #否则会打印全部内容
root:x:0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
[……省略部分内容……]
xjh@ubuntu:~/iot/tmp$ sed '/root/{s/bash/sh/;s/bin/usrbin/}' /etc/passwd
root:x:0:0:root:/root:/usrbin/sh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
[……省略部分内容……]
xjh@ubuntu:~/iot/tmp$ sed -n '/root/{s/bash/sh/p;s/bin/usrbin/}' /etc/passwd
root:x:0:0:root:/root:/bin/sh
xjh@ubuntu:~/iot/tmp$ sed -n '/root/{s/bash/sh/;s/bin/usrbin/p}' /etc/passwd
root:x:0:0:root:/root:/usrbin/sh
xjh@ubuntu:~/iot/tmp$ sed -n '/root/{s/bash/sh/p;s/bin/usrbin/p}' /etc/passwd
root:x:0:0:root:/root:/bin/sh
root:x:0:0:root:/root:/usrbin/sh
xjh@ubuntu:~/iot/tmp$

2、删除特定行命令d

如果要删除文本流中的特定行,可以使用删除命令d。

可以通过上面提到的两种行寻址方式,来匹配要删除的某些行。

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '3d' data4.txt 
This is line number 1.
This is line number 2.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '2,3d' data4.txt 
This is line number 1.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '3,$d' data4.txt 
This is line number 1.
This is line number 2.
xjh@ubuntu:~/iot/tmp$ sed '/number 3/d' data4.txt 
This is line number 1.
This is line number 2.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '/number 2/,/number 4/d' data4.txt 
This is line number 1.
xjh@ubuntu:~/iot/tmp$

3、插入命令i、附加命令a

插入命令i(insert的首字母),会在指定行之前增加一个新行。

附加命令a(append的首字母),会在指定行之后增加一个新行。

这两个命令的使用格式如下,其中command为i或者a,file表示要往哪个文件中插入或者附加(如果缺省,则默认插入或者附加到输入流中),new_line表示要添加的内容,而address表示往文件中的哪一行插入或者附加(可以通过之前说的两种行寻址方式来确定这个地址)。

sed '[address]command\new_line' file
xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ echo "Test line 2" | sed 'i\Test line 1'
Test line 1
Test line 2
xjh@ubuntu:~/iot/tmp$ echo "Test line 2" | sed 'a\Test line 1'
Test line 2
Test line 1
xjh@ubuntu:~/iot/tmp$ sed 'i\Test line 1'#因为缺省file,则默认从输入流获取内容
Test line 2 #因此要输入一行内容,并按回车
Test line 1 #接下来的两行是结果的显示。注意,如果不按ctrl+d产生EOF符号,会提示一直输入
Test line 2
xjh@ubuntu:~/iot/tmp$ sed '3i\Test line 1' data4.txt #在第3行前面插入一行
This is line number 1.
This is line number 2.
Test line 1
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '3a\Test line 1' data4.txt #在第3行后面插入一行
This is line number 1.
This is line number 2.
This is line number 3.
Test line 1
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '$a\Test line 1' data4.txt  #符号$表示数据最后一行
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
Test line 1
xjh@ubuntu:~/iot/tmp$ sed '/number 2/i\Test line 1' data4.txt 
This is line number 1.
Test line 1
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '$i\Test line 1' data4.txt #使用文本模式的行寻址方式定位行
This is line number 1.
This is line number 2.
This is line number 3.
Test line 1
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '2i\  #在指定行前插入或者指定行后附加多行文本的方法
> this is a cat.\
> this is a dog.' data4.txt
This is line number 1.
this is a cat.
this is a dog.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$

4、修改命令c

该命令可以修改数据流中整行文本的内容,其用法与插入命令或者附加命令一致,把i或者a改为c即可,这里不再赘述。但值得注意的是,如果在c命令中使用地址区间,那么不会把该地址区间的每一行都改为新行,而是用新的一行来替换这个地址区间里的所有行。

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed '2,3c\This is a cat.' data4.txt 
This is line number 1.
This is a cat.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ 

5、转换字符y

转换字符y是唯一可以处理单个字符的sed编辑器命令,使用格式如下:

sed '[address]y/inchar/outchar/' file

这个命令会将inchar中的第n个字符转换为outchar中的第n个字符,直到处理inchar中的所有字符。使用该命令时,要求inchar和outchar的长度一样,否则会报错。

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed 'y/123/789/' data4.txt 
This is line number 7.
This is line number 8.
This is line number 9.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ 

6、打印命令

在替换命令s中提到,可以利用替换标志p来与-n选项,来显示sed编辑器修改过的行。另外也有3个命令能够打印数据流中的信息。

(1)利用p命令打印行,其最常见的用法是打印包含匹配文本模式的行,这需要结合-n选项。

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed -n '/number 3/p' data4.txt 
This is line number 3.
xjh@ubuntu:~/iot/tmp$ sed -n '2,3p' data4.txt 
This is line number 2.
This is line number 3.
xjh@ubuntu:~/iot/tmp$ sed -n '/number 3/{
> p
> s/This/It/
> }' data4.txt
This is line number 3. #如果不带p标志,因为用了-n选项,则修改后的内容不会被打印出来
xjh@ubuntu:~/iot/tmp$ sed -n '/number 3/{ #这个例子表示,利用打印命令,在修改前查看原先行的内容
> p
> s/This/It/p
> }' data4.txt
This is line number 3.
It is line number 3.
xjh@ubuntu:~/iot/tmp$

(2)利用等号命令打印行号,即打印行在数据流中的当前行号。

xjh@ubuntu:~/iot/tmp$ sed '=' data4.txt
1
This is line number 1.
2
This is line number 2.
3
This is line number 3.
4
This is line number 4.
xjh@ubuntu:~/iot/tmp$ sed -n '/number 2/{
> p
> =
> }' data4.txt
This is line number 2.
2
xjh@ubuntu:~/iot/tmp$ 

(3)利用小写的L打印行,该命令可以打印数据流中的文本和不可打印的ASCII字符。不可打印的ASCII字符在显示结果中,一般以反斜杆加其八进制值,或者以C语言风格的形式显示,比如\t。

xjh@ubuntu:~/iot/tmp$ cat data5.txt 
This	is	line	number	1. #这里故意留了一行
xjh@ubuntu:~/iot/tmp$ sed -n 'l' data5.txt 
This\tis\tline\tnumber\t1.$
$
xjh@ubuntu:~/iot/tmp$xjh@ubuntu:~/iot/tmp$ cat data5.txt 
This	is	line	number	1. #这里的间隔是按了tab键产生的,即\t这个制表符
This	is	line	number	2.
xjh@ubuntu:~/iot/tmp$ sed -n 'l' data5.txt
This\tis\tline\tnumber\t1.$    #\t表示制表符,$表示换行符
This\tis\tline\tnumber\t2.$
xjh@ubuntu:~/iot/tmp$ 

7、写入命令w

该命令可以将一个文件中的某些行(如果指定)或者将标准输入中的内容(默认情况),写入到另一个文件中。如果是将文件中的某些行写入到另一个文件,可以通过之前提到的两种行寻址方式,查找到要写入的行。注意是将哪个文件中的内容,写到哪一个另外的文件,即注意格式。

xjh@ubuntu:~/iot/tmp$ sed '2,3 w test.txt' data4.txt  #将data4.txt文件中的第2到第3行的内容,写到文件test.txt中
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ cat test.txt 
This is line number 2.
This is line number 3.
xjh@ubuntu:~/iot/tmp$ 

可以利用该命令,结合文本模式匹配方式,从某个文件中提取想要的数据,并写入到新文件中。

xjh@ubuntu:~/iot/tmp$ cat data6.txt 
name	age	height
xjh	18	176
xjq	25	180
zzm	45	160
xjh@ubuntu:~/iot/tmp$ sed -n '/xjh/w xjh.txt' data6.txt 
xjh@ubuntu:~/iot/tmp$ cat xjh.txt 
xjh	18	176
xjh@ubuntu:~/iot/tmp$

8、读取命令r

该命令会将数字文件中的所有文本行都插到数据流中。注意是读取哪个文件的内容,插到哪个另外的文件中,即注意格式。

xjh@ubuntu:~/iot/tmp$ cat data4.txt 
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ cat data5.txt 
This	is	line	number	1.
This	is	line	number	2.
xjh@ubuntu:~/iot/tmp$ sed '/number 2/r data5.txt' data4.txt  #将data5,.txt的内容插入到data4.txt中指定的行的后面
This is line number 1.
This is line number 2.
This	is	line	number	1.
This	is	line	number	2.
This is line number 3.
This is line number 4.
xjh@ubuntu:~/iot/tmp$ 

该命令与删除命令配合使用,可以利用另一个文件中的数据来替代某个文件中的占位文本(即某个文本模板中的词语,利用该模板时,在该词语处添加内容)。

xjh@ubuntu:~/iot/tmp$ cat name.txt 
XJH
XJQ
ZZP
xjh@ubuntu:~/iot/tmp$ cat notice.txt 
Would the following people:
LIST
Please stand up!
xjh@ubuntu:~/iot/tmp$ sed '/LIST/{
> r name.txt
> d
> }' notice.txt
Would the following people:
XJH
XJQ
ZZP
Please stand up!
xjh@ubuntu:~/iot/tmp$ 

相关内容

热门资讯

18公里收取581元!广州交通... 2月24日晚,广州市交通运输局发布通报:2月24日,广州市交通运输局执法部门关注到媒体报道有乘客反映...
海水制氢,新突破 海水无须淡化、直接电解制氢的技术日趋成熟,中国不少地区也陆续开展电解海水制氢产业的探索应用实践。20...
求几本修真小说,文笔好一点的 求几本修真小说,文笔好一点的超级仙医 有爱情,亲情,友情,还有修真
倒计时!资阳首个百亿级项目全力... 四川在线记者 田姣 资阳观察 吴昊江项目介绍四川仕净高效太阳能电池片生产制造基地项目,总投资100亿...
大基建异动走强 多只高位人气... 周一,农业股逆势大涨,智慧农业、东方集团、中粮科技等涨停,雪榕生物、广宇集团、富邦科技等个股涨幅居前...
德国大选落幕,政治极化和“碎片... 转自:上观新闻据新华社报道,德国联邦选举委员会24日凌晨公布联邦议院(议会下院)选举初步计票结果,基...
国义招标股东广东地方铁路拟减持... 2月24日,国义招标公告,股东广东地方铁路计划在2025年3月17日至2025年6月16日期间,通过...
三生国健“减负”增厚业绩,娄竞... 聚焦自免赛道的三生国健(688336.SH),又向关联方沈阳三生出售了两条肿瘤药物管线。三生国健日前...
被列为被告!知名男演员涉嫌伤害... 据台媒最新报道,中国台湾演员李威因卷入精舍杀人案,今日他被第四度传唤调查,由证人身份改列被告,并同步...
寻一部武侠电影片 寻一部武侠电影片洪金宝的《山东响马》剧情 青龙堂主安如龙恃众横行,劫掠烧杀,山东地带被蹂躏至永无宁...
为什么我只爱自己 是我太幼稚吗 为什么我只爱自己 是我太幼稚吗可能是你小的时候缺少了这样一个童年,大尺尺圆了才会有这样困搭的想法,应...
广州官方通报打车18公里被收5... 转自:广州交通2月24日,广州市交通运输局执法部门关注到媒体报道有乘客反映“18公里路程被司机收取5...
百川畅银:预计2025年年中有... 上证报中国证券网讯(记者 霍星羽)百川畅银近日发布的投资者关系活动记录表显示,海外垃圾填埋气发电项目...
有没有男主喜欢女主是因为阴谋到... 有没有男主喜欢女主是因为阴谋到后面女主离开了男主发现自己爱上了女主的古代言情?《结缘》,《两只前夫一...
一汽解放与深圳集装箱运输协会签... e公司讯,近日,一汽解放与深圳集装箱运输协会战略合作签约暨25款港牵产品上市发布会在深圳举行。双方达...
吴说每日精选加密新闻 + 本周... 1.Bitrace:Bybit 被盗后 OTC 群体与 Crypto 支付公司将迎来大规模冻结潮Bi...
跃岭股份实控人筹划公司控制权转... 2月24日晚间,跃岭股份公告称,公司控股股东、实际控制人正在筹划公司控制权转让事宜,预计本次转让涉及...
【财经分析】信用债调整进行时 ... 转自:新华财经新华财经上海2月24日电(记者 杨溢仁)本轮利率债市场的下跌,已开始向信用债市场传导。...
10岁男孩独自出行 热心人“接... 2月18日,新余有个10岁男孩,送别外出务工的父亲后,居然背着奶奶独自坐火车,准备到南昌找朋友。关键...
哪吒背后4000多名动画人几乎... 来源:@21世纪经济报道微博 【#哪吒背后4000多名动...