Linux文本处理sed命令高级用法
Posted 白-胖-子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux文本处理sed命令高级用法相关的知识,希望对你有一定的参考价值。
sed 工作原理
- sed 即 Stream EDitor,和 vi 不同,sed是基于行的文本编辑器
- Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。
sed 模式空间
- sed每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),
- 接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。
- 一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。
- 如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。
- Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快。
sed 模式空间相关命令
- p 打印当前模式空间内容,追加到默认输出之后
- Ip 忽略大小写输出
- d 删除模式空间匹配的行,并立即启用下一轮循环
- a []text 在指定行后面追加文本,支持使用\\n实现多行追加
- i []text 在行前面插入文本
- c []text 替换行为单行或多行文本
- w file 保存模式匹配的行至指定文件
- r file 读取指定文件的文本至模式空间中匹配到的行后
- = 为模式空间中的行打印行号
- ! 模式空间中匹配行取反处理
- q 结束或退出sed
sed 保持空间
- sed 中除了模式空间,还另外还支持保持空间(Hold Space),
- 利用此空间,可以将模式空间中的数据,临时保存至保持空间,
- 从而后续接着处理,实现更为强大的功能。
- 模式空间可以理解为前台,保持空间可以理解为后台
sed 保持空间相关命令
- P 打印模式空间开端至\\n内容,并追加到默认输出之前
- h 把模式空间中的内容覆盖至保持空间中
- H 把模式空间中的内容追加至保持空间中
- g 从保持空间取出数据覆盖至模式空间
- G 从保持空间取出内容追加至模式空间
- x 把模式空间中的内容与保持空间中的内容进行互换
- n 读取匹配到的行的下一行覆盖至模式空间
- N 读取匹配到的行的下一行追加至模式空间
- d 删除模式空间中的行
- D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环
sed 模式空间和保持空间使用范例
模式空间覆盖保持空间,再保持空间覆盖模式空间
- 读取第一行,没有匹配/3/,用保持空间的空来覆盖模式空间,结果为空
- 读取第二行,没有匹配/3/,用保持空间的空来覆盖模式空间,结果为空
- 读取第三行,匹配到了/3/,将匹配到的3覆盖至保持空间,再将保持空间的3覆盖至模式空间,结果为3
- 读取第四行,没有匹配/3/,用保持空间的3覆盖至模式空间,结果为3
[root@C8-192 ~]# seq 4 | sed '/3/h;g'
3
3
模式空间覆盖保持空间,再保持空间追加模式空间
[root@C8-192 ~]# seq 4 | sed '/3/h;G'
1
2
3
3
4
3
模式空间追加保持空间,再保持空间覆盖模式空间
[root@C8-192 ~]# seq 4 | sed '/3/H;g'
3
3
模式空间追加保持空间,再保持空间追加模式空间
[root@C8-192 ~]# seq 4 | sed '/3/H;G'
1
2
3
3
4
3
模式空间替换保持空间,再模式空间覆盖保持空间
[root@C8-192 ~]# seq 4 | sed '/3/x;h'
1
2
2
4
模式空间替换保持空间,再模式空间追加保持空间
[root@C8-192 ~]# seq 4 | sed '/3/x;H'
1
2
1
2
4
模式空间替换保持空间,再保持空间覆盖模式空间
[root@C8-192 ~]# seq 4 | sed '/3/x;g'
3
3
模式空间替换保持空间,再保持空间追加模式空间
-
- 读取第一行,没有匹配/3/,用保持空间的空来追加到模式空间,结果为1下一行空
- 读取第一行,没有匹配/3/,用保持空间的空来追加到模式空间,结果为2下一行空
- 读取第三行,匹配到了/3/,将匹配到的3与保持空间空替换,再将保持空间的3追加至模式空间,结果为空下一行3
- 读取第四行,没有匹配/3/,用保持空间的3追加至模式空间,结果为4下一行3
[root@C8-192 ~]# seq 4 | sed '/3/x;G'
1
2
3
4
3
sed高级用法范例
打印偶数行
- ‘n;p’ 读取一行的下一行放到模式空间中打印出来
seq 10 | sed -n 'n;p'
2
4
6
8
10
打印奇数行
seq 10 | sed 'n;d'
1
3
5
7
9
一列分两列
- ‘N;s/\\n//’ 读取到匹配的一行以后,然后把读取到的这行的下一行追加到后边,
- 使用s/\\n//搜索替代把换行符替换为空,就可以直观的看到读取追加的效果
- 不约定条件表示匹配所有行
seq 10 | sed 'N;s/\\n//'
12
34
56
78
910
seq 10 | sed '/3/N;s/\\n//'
1
2
34
5
6
7
8
9
10
倒叙排列
seq 10 | sed '1!G;h;$!d'
10
9
8
7
6
5
4
3
2
1
seq 10 | sed -n '1!G;h;$p'
10
9
8
7
6
5
4
3
2
1
取匹配到的行的前一行
seq 10 | sed -n '/5/{g;1!p;};h'
4
取匹配到的行的后一行
seq 10 | sed -nr '/5/{n;p}'
6
查看匹配到的最后一行,功能类似于tail
seq 10 | sed 'N;D'
10
seq 10 | sed '$!d'
10
[root@C8-192 ~]# tail -n 1 /var/log/messages
Jun 1 18:22:49 C8-192 systemd[1]: Started dnf makecache.
[root@C8-192 ~]# cat /var/log/messages | sed 'N;D'
Jun 1 18:22:49 C8-192 systemd[1]: Started dnf makecache.
[root@C8-192 ~]# sed '$!d' /var/log/messages
Jun 1 19:22:54 C8-192 systemd[1]: Started dnf makecache.
调换匹配行的前后次序
seq 10 |sed '5h;9G;9!d'
9
5
sed '/i/h;/you/G;/you/!d;' iloveyou.log
you
i
显示匹配到的行的后两行,类似于tail -n 2
seq 10 | sed '$!N;$!D'
9
10
sed '$!N;$!D' /var/log/messages
Jun 1 19:22:54 C8-192 systemd[1]: dnf-makecache.service: Succeeded.
Jun 1 19:22:54 C8-192 systemd[1]: Started dnf makecache.
tail -n 2 /var/log/messages
Jun 1 19:22:54 C8-192 systemd[1]: dnf-makecache.service: Succeeded.
Jun 1 19:22:54 C8-192 systemd[1]: Started dnf makecache.
每行后边加个空行
sed '/^$/d;G' iloveyou.log
i
love
you
- 删除内容后把空位留着
[root@C8-192 ~]# sed '/love/d;G' iloveyou.log
i
you
[root@C8-192 ~]# sed '/love/d' iloveyou.log
i
you
用井号注释掉需要删除的内容
sed -r 's/(love)/##\\1/;G' iloveyou.log
i
##love
you
练习示例
1、删除centos8系统/etc/grub2.cfg文件中所有以空白开头的行行首的空白字符
sed -ri.bak 's/^[[:blank:]](.*)/\\1/' /etc/grub2.cfg
2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符
sed -ri.bak 's/^#+[[:blank:]](.*)/\\1/g' /etc/grub2.cfg
3、在centos8系统/root/iloveyou.log每一行行首增加#号
[root@C8-192 ~]# cat iloveyou.log
i
love
you
[root@C8-192 ~]# sed -ri.bak 's/(.*)/#\\1/g' iloveyou.log
[root@C8-192 ~]# cat iloveyou.log
#i
#love
#you
4、在/etc/fstab文件中不以#开头的行的行首增加#号
[root@C8-192 ~]# sed -n '/^[^#]/p' fstab.log
UUID=827b1562-fd3a-4e03-ad8b-f4c0b8def517 / xfs defaults 0 0
UUID=ea560777-7040-46e1-9931-633142400896 /boot ext4 defaults 1 2
UUID=5de69ef1-4e31-40b8-832f-91c00cd57873 /data xfs defaults 0 0
UUID=b3fd1c68-6653-41ff-8ecb-25fdcfeeced9 swap swap defaults 0 0
[root@C8-192 ~]# sed -r '/^[^#]/s/(.*)/#\\1/' fstab.log
#
# /etc/fstab
# Created by anaconda on Wed May 19 22:15:11 2021
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
#UUID=827b1562-fd3a-4e03-ad8b-f4c0b8def517 / xfs defaults 0 0
#UUID=ea560777-7040-46e1-9931-633142400896 /boot ext4 defaults 1 2
#UUID=5de69ef1-4e31-40b8-832f-91c00cd57873 /data xfs defaults 0 0
#UUID=b3fd1c68-6653-41ff-8ecb-25fdcfeeced9 swap swap defaults 0 0
5、处理/etc/fstab路径,使用命令取出其目录名和基名
echo "/etc/fstab" |awk -F'/' '{print $2,$3}'
etc fstab
6、利用sed 取出ifconfig命令中本机的IPv4地址
ifconfig | sed -nr '/eth0/{n;p}' | awk '{print $2}'
[root@C8-192 ~]# ifconfig | sed -nr '/eth0/{n;p}'
inet 10.0.0.192 netmask 255.255.255.0 broadcast 10.0.0.255
[root@C8-192 ~]# ifconfig | sed -nr '/eth0/{n;p}' | awk '{print $2}'
10.0.0.192
以上是关于Linux文本处理sed命令高级用法的主要内容,如果未能解决你的问题,请参考以下文章