sed基础

基本概念

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基础

常用选项

和其他常见命令不同,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只是影响了默认输出,如下:
sed基础

[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 读取下一行

读取匹配的行的下一行,读取之前依旧会输出模式空间里的行并且清空,如果下一行是最后一行则立刻退出,之后命令不在执行。流程大致如下:
sed基础

s 搜索替换命令

s命令是我们最常用的命令,"s"命令的语法格式为:其中"/"可以替换成任意其他单个字符。 s/REGEXP/REPLACEMENT/FLAGS
它使用 REGEXP去匹配行,将匹配到的那部分字符替换成 REPLACEMENT。FLAGS是 "s"命令的修饰符,常见的有"g"、"p"和"i"或"I"。
"g":表示替换行中所有能被 REGEXP匹配的部分。不使用 g时,默认只替换行中 的第一个匹配内容。此外,"g"还可以替换成一个数值 N,表示只替换行中第 N个 被匹配的内容。
"p":输出替换后模式空间中的内容。
"i"或"I":REGEXP匹配时不区分大小写。

[root@lbaby ~]# sed -n 's/root/&super/p' /etc/passwd
rootsuper:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/rootsuper:/sbin/nologin
不使用g的时候值替换行中匹配到的第一个

[root@lbaby ~]# sed -n 's/root/&super/pg' /etc/passwd
rootsuper:x:0:0:rootsuper:/rootsuper:/bin/bash
operator:x:11:0:operator:/rootsuper:/sbin/nologin

插入追加修改

[a|i|c] string
将string队列到内存中,当有输出动作的时候追上输出流进行追加,插入或替换然后进行输出

sed '/root/a\superman' /etc/passwd      在匹配到的行的下一行添加指定内容
[root@lbaby ~]# sed '/root/a\superman' /etc/passwd
root:x:0:0:root:/root:/bin/bash
superman
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
superman
……
sed '/root/i\superman' /etc/passwd      匹配到的行的上一行添加
[root@lbaby ~]# sed '/root/i\superman' /etc/passwd
superman
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
superman
operator:x:11:0:operator:/root:/sbin/nologin
sed '/root/c\superman' /etc/passwd      代替匹配到的行
[root@lbaby ~]# sed '/root/c\superman' /etc/passwd
superman
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
superman

高级命令

模式空间,保持空间

猜你喜欢

转载自blog.51cto.com/13672361/2106536
sed