sed简介
sed是一种新型的非交互的编辑工具,本质上与vi等编辑器一样提供编辑功能。与之不同的在于sed是一种非破坏的编辑工具,它不对文本进行修改,若想使修改生效,需要重定向到文本文件中。
sed工作方式
sed的工作方式如下图,sed在处理文件时,会将一行导入到模式空间(缓冲区中),在模式空间中按照我们需要的约束对其进行处理,最后根据需要输出到屏幕。因为其操作都是在模式空间中,不会对文件进行修改,因此sed是非破坏的编辑工具。
sed的文件查找
sed文件查找是基于正则表达式(不明白什么是正则表达式请自行百度)
简单的例子:
sed -n '/RE/p' filename
sed -n '/goodboy/p' filename
sed [option] ‘/RE/’ filename
这个表达式由四部分组成:
- 工具名字sed
- 操作命令[oprtions]
- 操作的文本’/RE/’(RE表示正则表达式)。后面会讲到,这其实是一个定址操作,即选定操作的地址。
- 操作文件fileanme
上面的命令表示在filename文件中 匹配到goodboy行,然后打印p出来。- n表示只打印出匹配行,如果没有-n。 sed会打印出所有文本。
定址
定址就是选择编辑的部分,可以用数字和正则表达式,以及二者一起表示,如果没有给定这个范围sed将会对全文进行操作。
如果给定数字,则表示一个行号,如果用,
分隔两个数字,则表示在这两行之间,$
表示最后一行。
在给出定址以后,我们就可以告诉sed应该进行哪些操作了(插入,打印,删除,修改等等)
例子:
sed '1,3d' filename
sed '/[Dd]eng/p' filename
例子中,我分别用了数字和正则表达式来定址,通常在定址之后我们需要对定址的内容进行编辑。删除或者打印等等。但是sed是非破坏性的编辑器,我们所有的更改都是在sed的模式空间中进行的,不会影响源文件。
另外,我们还可以通过!
来表示一个相反的操作。比如,我们希望删除没有hello的行:
sed '/hello/!d' filename
文件修改
我们之前多次提到sed是一个非破坏性的编辑器,那么修改功能也只能通过重定向的方式来解决了
sed '/hello/d' filename > temp
mv temp filename
sed的退出码
- 在sed语法错误的时候退出码不为0
- 在sed执行成功(不管是否匹配成功,只要语法正确)即返回0
sed范例
打印p
p是sed打印命令,默认情况下sed打印缓冲区中的所有内容。p配合-n一起使用,可以让sed打印选定内容。
如:
#sed test data : test.txt
hello
print all
2016/10/01
➜ sed '/hello/p' test.txt
#sed test data : test.txt
hello
hello
print all
2016/10/01
sed会输出匹配行,并且打印出整个文本。
➜ sed -n '/hello/p' test.txt
hello
当sed配合-n
使用时,sed仅仅打印选定的行。
删除d
d命令用于删除sed的行,sed先从文件中读取文本到缓冲区,在缓冲区中进行sed操作。然后输出到屏幕上。当设置了d命令之后,该行将会在缓冲区中被删除,不会打印到屏幕上。
➜ sed '2,$d' test.txt
#sed test data : test.txt
➜ sed '1d' test.txt
hello
print all
2016/10/01
替换命令s
sed ‘s/选择文本/替代/g’
通常选择的文本我们利用正则表达式来选定的。
末尾的g表示全局替换,如果没有选定,则表示替换每一行的第一个。
➜ shell_test cat test.txt
#sed test data : test.txt
hello hello2
hello hello2
print all
2016/10/01
➜ shell_test sed 's/hello/seb/' test.txt
#sed test data : test.txt
seb hello2
seb hello2
print all
2016/10/01
➜ shell_test sed 's/hello/seb/g' test.txt
#sed test data : test.txt
seb seb2
seb seb2
print all
2016/10/01
组合命令
通过组合上述的命令,可以完成更多,更复杂的工作。
例如我们将定址和命令放在一起,可以在选定的范围内对文本进行操作。
如:
我们在start和end之间进行一些操作
➜ shell_test cat test.txt
#sed test data : test.txt
hello hello2
hello hello2
start
print all
2016/10/01
end
➜ shell_test sed -n '/start/,/end/p' test.txt
start
print all
2016/10/01
end
由于我们使用了正则表达式的匹配,则需要用/start/
,/end/
来表示选定范围,如果直接利用行号来定址则可以使用’1,3’的方式表示1行~3行(包含1行和3行)
将定址与其他操作结合:
➜ shell_test sed -n '/start/,/end/s/10/11/p' test.txt
2016/11/01