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命令高级用法的主要内容,如果未能解决你的问题,请参考以下文章

Linux-sed

Linux bash 文本处理命令awk,sed,grep 用法

文本处理三剑客之-sed高级用法

Linux高级文本处理之sed

sed和awk之sed篇(含sed高级用法)

Linux文本处理三剑客grepsedawk用法详解