Shell命令——sed命令

以下内容整理于《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$ 

猜你喜欢

转载自blog.csdn.net/oqqHuTu12345678/article/details/129344609