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的常用选项很少,这里挑几个常用的介绍一下。
-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 读取下一行
读取匹配的行的下一行,读取之前依旧会输出模式空间里的行并且清空,如果下一行是最后一行则立刻退出,之后命令不在执行。流程大致如下:
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
sed高级命令
之前我们用到的sed命令都是一行一行的进行处理文本的,不过有些时候单行处理可能并不能满足我们的需要,所以sed还提供了多行模式,多行模式的命令主要有NPD这三个,
N:读取匹配到的行的下一行追加至模式空间
P:打印模式空间开端至\n内容,并追加到默认输出之前
D:如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本, 并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间 不包含换行符,则会像发出d命令那样启动正常的新循环
首先还是先看一下N命令的大致流程图,P和D命令在懂了N命令之后也容易理解。
需要注意的是,之所以叫多行模式是因为可以存放不止两行,如下示例:
[root@VM_161_150_CentOS ~]# cat /etc/passwd |sed -n ‘2{N;p}’
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
### 读取第二行的下一行,然后输出模式空间中的内容,此时模式空间中有两行
[root@VM_161_150_centos ~]# cat /etc/passwd |sed -n ‘2{N;N;N;p}’
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
### 使用多个N命令可以读取多行进模式空间
模式空间
除了模式空间,sed命令还有另外一个空间叫保持空间,其实保持空间很容易理解,之前我们说sed在处理文本的时候都是在模式空间中进行,但有时候有些复杂的操作单一的模式空间可能无法满足我们的需求于���就有了模式空间,模式空间你可以看作是模式空间的翻版,但是这个空间通常是空闲的,并不处理数据,只在有需要的时候和模式空间进行一些必要的数据交换。下面是模式空间中的常用命令。
h: 把模式空间中的内容覆盖至保持空间中
H:把模式空间中的内容追加至保持空间中
g: 从保持空间取出数据覆盖至模式空间
G:从保持空间取出内容追加至模式空间
x: 把模式空间中的内容与保持空间中的内容进行互换
打个比方,假如你有两个杯子,
h 就相当于吧二个杯子中的东西替换为第一个杯子中的,
H就相当于把第一个杯子中的东西放到第二个杯子中,并且第二个杯子中的东西还在,
g和h相似,不过是反了过来吧第一个杯子中的东西替换为第二个杯子中的,
G也是和H类似,x就相当于把两个杯子中的东西进行了交换。
下面通过几个示例演示一下
[root@VM_161_150_centos ~]# seq 1 6| sed -n ‘1,2H;4p;5{x;p}’
4
1
2
解释一下,-n是不显示默认输出内容,1,2H是将前两行追加至保持空间,4p显示第四行,5{x;p}是在第五行的时候交换保持空间和模式空间中的内容并且输出。注意输出中的空行,这是因为H命令追加的时候是添加换行符,由于保持空间默认是空的,所以添加换行符之后就多了一个空行。以用下面的命令先往保持空间覆盖一行然后追加。
[root@VM_161_150_centos ~]# seq 1 6| sed -n ‘1h;2H;4p;5{x;p}’
4
1
2
第一个循环结束之后:模式空间为空,保持空间为第一行内容
第二个循环,将第二行追加到模式空间,此时模式空间为两行内容
第三个循环,没有匹配内容,不执行操作,模式空间和保持空间内容不变
第四个循环,读取第四行并输出,保持空间内容不变
第五个循环,读入第五行,然后和保持空间中的内容交换,之后输出。
本文永久更新链接地址:https://www.linuxidc.com/Linux/2018-05/152196.htm