sed简介
也被称作流编辑器,用来对文本进行过滤和替换操作。
sed数据处理流程是读取文档的一行至模式空间,然后对该行执行相应的sed指令,指令完成后输出该行并清空模式空间,依次循环直至文档数据结尾。
这些命令可以从键盘中输入或者从文件中读取。
sed命令会执行如下操作
- 一次从键盘或文件中读取一行数据到模式空间;
- 根据提供的命令匹配数据;
- 按照命令修改数据;
- 将编辑后的数据输出到STDOUT,默认是显示器,然后清空模式空间。
语法格式
sed options script file
sed常用选项
选项 | 描述 | 选项 | 描述 |
--version | 显示版本 | --help | 显示帮助文档 |
-n,--quiet,--silent |
静默输出,默认情况下sed会在脚本指令执行完毕后自动打印模式空间的内容,该选项屏幕自动打印 |
-e script | 执行多个脚本命令 |
-f script-file | 从文件中读取脚本指令 | -i,--in-place | 直接修改源文件 |
-l N | 指定l指令可以输出行长度 | --posix | 禁用GNU sed扩展功能 |
-r | 在脚本中使用扩展正则表达式 | -s,--separate | 默认情况下,sed将把输入的多个文件名作为一个长的连续输入流,而GNU sed允许把他们当作单独的文件 |
-u,--unbuffered | 最低限度的缓存输入与输出 |
sed常用指令
指令 | 描述 | 指令 | 描述 |
s | 替换 | d | 删除 |
a | 追加 | i | 插入 |
c | 修改 | l | 打印(显示非打印字符) |
y | 按字符转换 | L | 打印(不显示非打印字符) |
p | 打印 | r | 读入文件 |
w | 保存到文件 | q | 退出 |
在命令行使用sed
默认输出到显示器上,s命令会把第一个字符串替换为第二个字符串。
[root@tzPC 19Unit]# echo "This is a test" | sed 's/test/big test/' This is a big test
修改文件中的数据
sed编辑器命令并不会修改文本文件的数据,它只会读取并修改后发送到STDOUT描述符,默认为显示器。
[root@tzPC 19Unit]# cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. [root@tzPC 19Unit]# sed 's/dog/cat/' data1.txt The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat.
在命令行使用多条匹配命令
写法一
sed命令行上执行多个命令,使用-e选项,并使用分号隔开。
[root@tzPC 19Unit]# cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. [root@tzPC 19Unit]# sed -e 's/brown/green/;s/dog/cat/' data1.txt The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat.
写法二
注意要在最后一个单引号所在行结束命令
[root@tzPC 19Unit]# sed -e ' > s/brown/green/ > s/fox/elephant/ > s/dog/cat/' data1.txt The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat.
写法三
[root@tzPC 19Unit]# sed -e 's/brown/green/' -e 's/dog/cat/' data1.txt The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat. The quick green fox jumps over the lazy cat.
从文件中读取编辑器命令
可以把sed命令写在文件中,用-f选项指定
[root@tzPC 19Unit]# vim script1.sed [root@tzPC 19Unit]# cat script1.sed s/brown/green/ s/fox/elephant/ s/dog/cat/ [root@tzPC 19Unit]# sed -f script1.sed data1.txt The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat. The quick green elephant jumps over the lazy cat.
s命令替换
s命令默认只替换每行文本中出现的第一个字符串。
要替换每行中不同位置出现的文本需要使用替换标记。
四种替换标记
- 数字:表明新文本将替换第几处模式匹配的地方
- g:替换所有匹配的文本
- p:打印模式空间的行
- w file:直接将执行结果写入到文件中
数字举例
只替换每行第二次出现的test
[root@tzPC 19Unit]# cat data4.txt This is a test of the test script. This is the second test of the test script.
[root@tzPC 19Unit]# sed 's/test/trial/2' data4.txt This is a test of the trial script. This is the second test of the trial script.
默认情况下,sed通过一次仅读取一行内容到模式空间并使用命令处理,输出此行,接着清空模式空间读下一行,依次循环读完整个文件内容。
-n选项会禁止自动打印模式空间中的内容。
-p选项打印模式空间的内容,结合-n使用就会打印执行命令成功的行。
[root@tzPC 19Unit]# cat data5.txt This is a test line. This is a different line. [root@tzPC 19Unit]# sed -n 's/test/trial/p' data5.txt This is a trial line.
如果不加-n,效果如下
[root@tzPC 19Unit]# sed 's/test/trial/p' data5.txt This is a trial line. #sed读取文本第一行到模式空间,执行命令后,发现匹配替换条件执行命令后,p选项会打印模式空间的内容,接着sed会按照默认再输出一次模式空间的内容,所以会输出1跟2行 This is a trial line. This is a different line.#,接着就会清空模式空间;读取下一行到模式空间执行命令再按照默认输出成为第3行。
-g选项替换所有匹配的文本,但他不输出,如果加-n就什么也不显示了,如果要查看匹配成功后的文本可配合p使用
[root@tzPC 19Unit]# sed -n 's/line/file/g' data5.txt [root@tzPC 19Unit]# sed -n 's/line/file/gp' data5.txt This is a test file. This is a different file.
替换分隔符
sed命令默认使用正斜线/作为分隔符,如果字符串中出现正斜线/需要使用来转义
如将C shell替换/etc/passwd中的bash shell
[root@tzPC 19Unit]# sed 's//bin/bash/in/csh/' /etc/passwd
这种情况可以使用其他字符作为分隔符
如使用感叹号最为分隔符
[root@tzPC 19Unit]# sed 's!/bin/bash!/bin/csh!' /etc/passwd
使用寻址
两种行寻址
- 以数字形式表示行区间
- 用文本模式过滤
数字方式的行寻址
如只修改第二行
[root@tzPC 19Unit]# sed '2s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
修改第二跟三行
[root@tzPC 19Unit]# sed '2,3s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy dog.
修改第二行到最后
[root@tzPC 19Unit]# sed '2,$s/dog/cat/' data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat. The quick brown fox jumps over the lazy cat
first~step指定first开始,step为步长,如1~2,指定第1行第3行第5行...为操作地址,2~5指定第二行每5行匹配一次操作地址
打印文件奇数行
[root@tzPC 19Unit]#sed -n '1~2' test.txt
文本模式寻址
使用正斜线/将要指定的文本圈起来
如只修改用户tz的默认shell
[root@tzPC 19Unit]# sed -n '/tz/s/bash/csh/p' /etc/passwd tz:x:1000:1000::/home/tz:/bin/csh [root@tzPC 19Unit]# grep tz /etc/passwd tz:x:1000:1000::/home/tz:/bin/bash
使用多条命令{}
如果有多条命令可以使用花括号
[root@tzPC 19Unit]# sed '2{ > s/fox/elephant/ > s/dog/cat/ > }' data1.txt The quick brown fox jumps over the lazy dog. The quick brown elephant jumps over the lazy cat. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
修改第3条到最后
[root@tzPC 19Unit]# sed '3,${ > s/brown/green/ > s/lazy/active/ > }' data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick green fox jumps over the active dog. The quick green fox jumps over the active dog.
注意如果满足第一个条件p会直接输出,所以就没有执行第二条命令,第二行的dog还是dog而不是cat。
[root@tzPC 19Unit]# sed '2{ s/fox/elephant/p s/dog/cat/ }' data1.txt The quick brown fox jumps over the lazy dog. The quick brown elephant jumps over the lazy dog. The quick brown elephant jumps over the lazy cat. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
d命令删除行
匹配到的行一旦被删除,模式空间变为空,删除命令会自动读取新的输入行,重新执行脚本命令。
命令d会删除匹配到的所有行,不写条件默认全部匹配,所以就会删除所有行。
[root@tzPC 19Unit]# cat data1.txt The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. [root@tzPC 19Unit]# sed 'd' data1.txt
可使用数字指定区间
[root@tzPC 19Unit]# cat data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. [root@tzPC 19Unit]# sed '3d' data6.txt This is line number 1. This is line number 2. This is line number 4. [root@tzPC 19Unit]# sed '2,3d' data6.txt This is line number 1. This is line number 4. [root@tzPC 19Unit]# sed '3,$d' data6.txt This is line number 1. This is line number 2.
可使用文本指定区间
[root@tzPC 19Unit]# sed '/number 1/d' data6.txt This is line number 2. This is line number 3. This is line number 4.
删除文本1开头,3结尾所有文本
[root@tzPC 19Unit]# sed '/1/,/3/d' data6.txt This is line number 4.
这里需要注意,文本1进入删除匹配,到文本3结束,但是文本中后续还有一个文本1,所以又进入删除模式,但未能匹配到后续的3,所以会删除余下所有文本
[root@tzPC 19Unit]# cat data7.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is line number 1 again. This is text you want to keep. This is the last line in the file. [root@tzPC 19Unit]# sed '/1/,/3/d' data7.txt This is line number 4.
只删除行123可以使用
[root@tzPC 19Unit]# sed '/1./,/3./d' data7.txt This is line number 4. This is line number 1 again. This is text you want to keep. This is the last line in the file.
或者使用数字匹配
[root@tzPC 19Unit]# sed '1,3d' data7.txt This is line number 4. This is line number 1 again. This is text you want to keep. This is the last line in the file.
删除以Bresnahan开始的行
[root@tzPC 19Unit]# cat data11.txt Blum, R Browncoat McGuiness, A Alliance Bresnahan, C Browncoat Harken, C Alliance [root@tzPC 19Unit]# sed '/^Bresnahan/d' data11.txt Blum, R Browncoat McGuiness, A Alliance Harken, C Alliance
i命令插入跟a命令附加
插入命令i会在指定行前增加一行
附加命令a会在指定行后增加一行
举例:使用插入命令会出现在数据流文本前面
[root@tzPC ~]# echo "Test Line 2" | sed 'iTest Line 1' Test Line 1 Test Line 2
使用附加命令会出现在数据流文本后面
[root@tzPC ~]# echo "Test Line 2" | sed 'aTest Line 1' Test Line 2 Test Line 1
将新行插入到第3行前
[root@tzPC 19Unit]# sed '3i > This is an inserted line.' data6.txt This is line number 1. This is line number 2. This is an inserted line. This is line number 3. This is line number 4.
将新行附加到数据流末尾
[root@tzPC 19Unit]# sed '$a > This is a new line of text.' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is a new line of text.
插入或附加多行文本,需要对文本行尾加
[root@tzPC 19Unit]# sed '1i > This is one line of new text. > This is another line of new text.' data6.txt This is one line of new text. This is another line of new text. This is line number 1. This is line number 2. This is line number 3. This is line number 4.
在1行前插入,在3行前插入,则不需要对文本行尾加
[root@tzPC 19Unit]# sed '1i > This is one line of new text. > 3i > This is anther line of new text' data6.txt This is one line of new text. This is line number 1. This is line number 2. This is anther line of new text This is line number 3. This is line number 4.
c命令修改行
修改第三行
[root@tzPC 19Unit]# sed '3c > This is a changed line of text.' data6.txt This is line number 1. This is line number 2. This is a changed line of text. This is line number 4.
也可以使用文本寻址
[root@tzPC 19Unit]# sed '/number 3/c > This is a changed line of text.' data6.txt This is line number 1. This is line number 2. This is a changed line of text. This is line number 4.
使用地址区间,会修改这区间内的所有行
[root@tzPC 19Unit]# sed '2,3c > This is a new line of text.' data6.txt This is line number 1. This is a new line of text. This is line number 4.
y命令转换
transform命令简写y
语法格式
[address]y/inchars/outchars/
转换命令会对inchars跟outchars值一一转换,如果两者长度不同,会报错
转换命令会把整个文本所有的指定字符自动进行转换
举例,如下1、2、3行的数字被换成了7、8、9
[root@tzPC 19Unit]# sed 'y/123/789/' data6.txt This is line number 7. This is line number 8. This is line number 9. This is line number 4.
举例
[root@tzPC 19Unit]# echo "This 1 is a test of 1 try." | sed 'y/123/456/' This 4 is a test of 4 try.
p、=、l打印命令
- p命令用来打印文本行;
- =命令用来打印行号;
- l命令用来列出行
p命令
可以看到echo命令输出到管道符传入给sed命令,sed命令默认会输出到显示器,p命令也会将匹配条件的文本行输出,默认是匹配所有,所以是两条。
[root@tzPC 19Unit]# echo "this is a test" | sed 'p' this is a test this is a test [root@tzPC 19Unit]# echo "this is a test" | sed -n 'p' this is a test
打印匹配文本的行
[root@tzPC 19Unit]# sed -n '/number 3/p' data6.txt This is line number 3.
打印行区间
[root@tzPC 19Unit]# sed -n '2,3p' data6.txt This is line number 2. This is line number 3.
打印修改之前的文本,再打印修改之后的文本
[root@tzPC 19Unit]# sed -n '/3/{ > p > s/line/test/p > }' data6.txt This is line number 3. This is test number 3.
打印行号
=命令会打印出行号,行号由换行符决定,每一个换行符都被认为是一行
[root@tzPC 19Unit]# sed '=' data1.txt 1 The quick brown fox jumps over the lazy dog. 2 The quick brown fox jumps over the lazy dog. 3 The quick brown fox jumps over the lazy dog. 4 The quick brown fox jumps over the lazy dog.
找出匹配行跟行号
[root@tzPC 19Unit]# sed -n '/number 4/{ > = > p > }' data6.txt 4 This is line number 4.
列出行
列出list命令缩写l
可以打印不可见的ASCII字符,如制表符,换行符
举例:行尾会使用$表示
[root@tzPC 19Unit]# cat data9.txt This line contains tabs. [root@tzPC 19Unit]# sed -n 'l' data9.txt This line contains tabs.$
w命令写入文件
w命令用于写入文件
举例:将data6.txt的前两行写入到test.txt
[root@tzPC 19Unit]# sed '1,2w test.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. [root@tzPC 19Unit]# cat test.txt This is line number 1. This is line number 2.
根据文本匹配写入
[root@tzPC 19Unit]# cat data11.txt Blum, R Browncoat McGuiness, A Alliance Bresnahan, C Browncoat Harken, C Alliance [root@tzPC 19Unit]# sed -n '/Browncoat/w Browncoats.txt' data11.txt [root@tzPC 19Unit]# cat Browncoats.txt Blum, R Browncoat Bresnahan, C Browncoat
w选项会使包含匹配模式的行会输出到文件
[root@tzPC 19Unit]# sed 's/test/trial/w test.txt' data5.txt
This is a trial line.
This is a different line.
[root@tzPC 19Unit]# cat test.txt
This is a trial line.
#注意是包含匹配模式的行才会输出到文件test.txt中
r命令读取数据
read读取缩写r
举例,将data12.txt中的内容读取到data6.txt的第3行后
[root@tzPC 19Unit]# cat data12.txt This is an added line. This is the second added line. [root@tzPC 19Unit]# sed '3r data12.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is an added line. This is the second added line. This is line number 4.
使用文本匹配,将data12.txt内容读取到data6.txt的number 2文本后
[root@tzPC 19Unit]# sed '/number 2/r data12.txt' data6.txt This is line number 1. This is line number 2. This is an added line. This is the second added line. This is line number 3. This is line number 4.
将data12.txt的内容读取到data6.txt的末尾
[root@tzPC 19Unit]# sed '$r data12.txt' data6.txt This is line number 1. This is line number 2. This is line number 3. This is line number 4. This is an added line. This is the second added line.
这里有个例子,文件notice.std中有个占位符LIST,需要将文件data11.txt的数据读取到占位符所在地
[root@tzPC 19Unit]# cat notice.std Would the following people: LIST please report to the ship's captain. [root@tzPC 19Unit]# sed '/LIST/{ > r data11.txt > d > }' notice.std Would the following people: Blum, R Browncoat McGuiness, A Alliance Bresnahan, C Browncoat Harken, C Alliance please report to the ship's captain.
学习来自:《Linux命令行与Shell脚本大全 第3版》第19章
参考来自:《Linux运维之道 第2版》 第3章