sed是一款强大的文本处理工具,全程叫stream editor,翻译过来就是流编辑器。
sed在处理文件时会依次把文件每一行读入缓冲区,称为模式空间,处理完成后在屏幕显示并读入下一行,直到文件结束或者指定的处理位置结束,处理过程不改变文件内容,除非使用重定向存储输出。其循环大致如下:
1、读取输入流的一行到模式空间
2、对模式空间中的内容执行script
3、默认输出并且清空模式空间
4、读取输入流的下一行到模式空间
5、对模式空间中的内容执行script
……
其中第一步的读取我们可以通过定制来控制sed读取输入流的位置,第二步的的script部分是我们操作的重点,注意第三步我们无法干预,即使使用 -n选项也只是输出空内容并非没有输出动作。
其命令格式如下:
sed -[opt] 'script' input_stream
其中script就是sed的命令部分也叫做sed脚本,是sed内部命令的集合,其格式如下:addr1[,addr2]cmdlist其中例如要对file第2行到第4行进行删除可以执行sed '2,4d' file其中,2,4用来指定要操作文件的位置
常用选项
和其他常见命令不同,sed的常用选项很少,这里挑几个常用的介绍一下。
-n 默认情况下sed会在匹配处理结束后将模式空间中的内容输出到屏幕上,使用-n之后会使得sed不在输出默认空间中的内容而是输出空内容,注意-n是使默认输出为空而不是禁用默认输出动作。
[root@lori bin]$·sed -n '1,3p' file
1
2
3
[root@lori bin]$·sed '1,3p' file
1
1
2
2
3
3
其中p命令用来显示行,之所以第二个命令中每一行都显示两次就是因为在不加-n的情况下sed会默认输出一次
-e 多点操作,但我的理解更像是sed内部的管道如下:
[root@lori bin]$·echo "what are you doing"| sed -e 's/what/how/' -e 's/how/hello/'
hello are you doing
解释一下上面的命令,其中s是替换命令,第一个-e 's/what/how/' 把输入中的what换成了how,然后第二个-e 's/how/hello/' 把第一个结果中的how又换成hello
-i'.bak' 将源文件重命名,并保存临时文件,其实现方式是sed在编辑文件的时候会将文件的修改写入到临时文件中,然后将源文件重命名并且把临时文件命名为源文件名。可以只用 -i 不进行备份,临时文件会将源文件覆盖,bak部分为自定义内容,可以使用* 代表源文件名,如sed -i'bak_*' script file 的结果是将源文件名加bak_前缀,并将临时文件保存。
[root@lori test]$·ls -i
1190752 passwd
[root@lori test]$·sed -i.bak '1,3d' passwd
[root@lori test]$·ls -i
1190753 passwd 1190752 passwd.bak
[root@lori test]$·ls -i
1190753 passwd 1190752 passwd.bak
[root@lori test]$·sed -i '1,3d' passwd
[root@lori test]$·ls -i
1190754 passwd 1190752 passwd.bak
上面第一个实验中,修改后的passwd文件的inode已经发生变化,而passwd.bak才是源文件,第二个实验中,单独使用-i选项后源passwd已经没有了,而是生成了一个全新的passwd文件。
-r 使用扩展正则而非基础正则。
定址表达式
当sed将输入流中的行读入到匹配空间之后就开始对读入的文本进行匹配,符合条件的执行后续命令,不符合条件的直接输出清空模式空间读取下一行进行匹配,匹配的过程成为定址,其格式为[addr1][,addr2],总体来说可以分为下面几种情况。
1、addr1和addr2都不指定的时候表示匹配所有行
2、指定一个地址的时候表示只有能被addr1表达式匹配的行
3、两个都指定的时候表示从addr1到addr2
其中,无论是addr1还是addr2都支持以下几种表达方式
N. 直接指定行号,如:sed -n '2,3p' file 显示file第2行到第3行
/REGEXP/ 正则表达式,如:sed -n '/^root/,/ftp/p' file 显示第一个匹配到的root开头的行到第一个包含ftp的行
$ 匹配最后一行(需要注意的是sed在处理完一个文件之前并不知道文件有多行,所以类似$-n行的写法是错误的)如:sed -n '$p' file 显示文件的最后一行
~符号,步进,例如sed -n '1~3p' file表示从第一行开始每隔三行进行输出显示
'ADDR1,+N' 匹配 ADDR1和其后的 N行。
另外在定址表达式后面加上!表示匹配未被表达式匹配到的行。例如:sed -n '3,6!p' file不显示文件3到6行
常用命令
不过多的介绍命令,而是通过流程图尝试理解sed运行原理
输出命令p
前面已经见过很多次了,p命令会输出当前模式空间中的内容,即使使用了-n,严格来说-n只是影响了默认输出,如下:
[root@lbaby ~]# echo -e "abc\ndef"|sed '2p'
abc
def \\ p命令输出
def \\ 默认输出
d命令
d命令用来清空当前模式空间中的内容,其循环和p命令类似,需要注意的是d后面的命令不会执行,因为模式空间中没有内容。如:
[root@lbaby ~]# echo -e "abc\ndef"|sed '2d'
abc
q或Q退出命令
q和Q用来立即退出sed程序。不同的是q命令依旧会执行默认输出,而Q命令直接退出,同时这两个命令都可以指定程序退出状态码:
[root@lbaby ~]# echo -e "abc\ndef"|sed '1q 3'
abc
[root@lbaby ~]# echo $?
3
[root@lbaby ~]# echo -e "abc\ndef"|sed '1Q 4'
[root@lbaby ~]# echo $?
4
注意第一条命令中的输出来自默认输出并非q命令,验证这一点很简单,加上 -n选项就能明白了。其大概流程如下图:
sed基础
n 读取下一行