天天看点

Linux-文本处理三剑客之sed

作者:不寐旋律

1 sed 工作原理

sed 即 Stream EDitor,和 vi 不同,sed是行编辑器

Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快

Linux-文本处理三剑客之sed

1.1sed 基本用法

格式:

sed [选项]... 'script;script;...' 文件名...

常用选项:

  • -n 不输出模式空间内容到屏幕,即不自动打印
  • -e 多点编辑
  • -f FILE 从指定文件中读取编辑脚本
  • -r, -E 使用扩展正则表达式
  • -i.bak 备份文件并原处编辑

script格式:

'地址命令'

地址格式:

1. 不给地址:对全文进行处理

2. 单地址:

  • #:指定的行,$:最后一行
  • /pattern/:被此处模式所能够匹配到的每一行

3. 地址范围:

  • #,# #从#行到第#行,3,6 从第3行到第6行
  • #,+# #从#行到+#行,3,+4 表示从3行到第7行
  • /pat1/,/pat2/
  • #,/pat/

4. 步进:~

  • 1~2 奇数行
  • 2~2 偶数行

命令:

p :打印当前模式空间内容,追加到默认输出之后
Ip :忽略大小写输出
d :删除模式空间匹配的行,并立即启用下一轮循环
a [\]text :在指定行后面追加文本,支持使用\n实现多行追加
i [\]text :在行前面插入文本
c [\]text :替换行为单行或多行文本
w file :保存模式匹配的行至指定文件
r file :读取指定文件的文本至模式空间中匹配到的行后
= :为模式空间中的行打印行号
! :模式空间中匹配行取反处理
s/pattern/string/修饰符 :查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
替换修饰符:
g :行内全局替换
p :显示替换成功的行
w  /PATH/FILE :将替换成功的行保存至文件中
I,i  :忽略大小写           

案例:

[root@nginx ~]# sed ' '
nihao
nihao
test   
test
[root@nginx ~]# sed ' ' /etc/issue
\S
Kernel \r on an \m

[root@nginx ~]# sed 'p' /etc/issue
\S
\S
Kernel \r on an \m
Kernel \r on an \m

[root@nginx ~]# sed -n '1p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@nginx ~]#
[root@nginx ~]# ifconfig  ens33| sed '2p'
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.223.111  netmask 255.255.255.0  broadcast 192.168.223.255
        inet 192.168.223.111  netmask 255.255.255.0  broadcast 192.168.223.255
        inet6 fe80::20c:29ff:fe36:1ac8  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:36:1a:c8  txqueuelen 1000  (Ethernet)
        RX packets 2369  bytes 154975 (151.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 157  bytes 19153 (18.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@nginx ~]# ifconfig  ens33| sed -n '2p'
        inet 192.168.223.111  netmask 255.255.255.0  broadcast 192.168.223.255
[root@nginx ~]# 

[root@nginx ~]# sed -n '$p' /etc/passwd
zhangsan:x:1003:1003::/home/zhangsan:/bin/bash
[root@nginx ~]
 
 [root@nginx ~]# ifconfig ens33 |sed -n '/netmask/p'
        inet 192.168.223.111  netmask 255.255.255.0  broadcast 192.168.223.255
[root@nginx ~]#

[root@nginx ~]# df | sed -n '/^\/dev\/sd/p'
/dev/sda1                 406180  132808   273372   33% /boot
[root@nginx ~]# 
[root@nginx ~]# seq 10 | sed -n '3,6p'
3
4
5
6
[root@nginx ~]#
[root@nginx ~]# seq 10 | sed -n '3,+2p'
3
4
5
[root@nginx ~]# seq 10 | sed -n '6,$p'
6
7
8
9
10
[root@nginx ~]# seq 10 |sed -n '1~2p'
1
3
5
7
9
[[root@nginx ~]# seq 10 |sed -n '2~2p'
2
4
6
8
10

#删除所有以#开头的行
[root@nginx ~]#sed -i '/^#/d' fstab
 
#只显示非#开头的行
[root@nginx ~]#sed -n '/^#/!p' fstab

# 获取分区利用率
[root@nginx ~]# df | sed -En '/^\/dev\/sd/s@.* ([0-9]+)%.*@\1@p'
33
[root@nginx ~]#           

练手:

sed '2p' /etc/passwd
sed  -n '2p' /etc/passwd
sed  -n '1,4p' /etc/passwd
sed  -n '/root/p' /etc/passwd
sed  -n '2,/root/p' /etc/passwd 从2行开始
sed  -n '/^$/=' file 显示空行行号
sed  -n  -e '/^$/p' -e '/^$/=' file
Sed'/root/a\superman' /etc/passwd行后
sed '/root/i\superman' /etc/passwd 行前
sed '/root/c\superman' /etc/passwd 代替行
sed '/^$/d' file
sed '1,10d'   file
nl   /etc/passwd | sed '2,5d'
nl   /etc/passwd | sed '2a tea'
sed 's/test/mytest/g' example
sed -n 's/root/&superman/p' /etc/passwd 单词后
sed -n 's/root/superman&/p' /etc/passwd 单词前
sed -e 's/dog/cat/' -e 's/hi/lo/' pets  
sed -i.bak  's/dog/cat/g' pets           

案例:取IP 地址

[root@nginx ~]# ifconfig ens33 |sed -nr "2s/[^0-9]+([0-9.]+).*/\1/p"
192.168.223.111
[root@nginx ~]#
[root@nginx ~]# ifconfig ens33 | sed -En '2s/^[^0-9]+([0-9.]{7,15}).*/\1/p'
192.168.223.111
[root@nginx ~]#
[root@nginx ~]# ifconfig ens33 | sed -rn '2s/^[^0-9]+([0-9.]+) .*$/\1/p'
192.168.223.111
[root@nginx ~]#
[root@nginx ~]# ifconfig ens33 | sed -n '2s/^.*inet //p' | sed -n 's/netmask.*//p'
192.168.223.111  
[[root@nginx ~]# ifconfig ens33 | sed -n '2s/^.*inet //;s/ netmask.*//p'
192.168.223.111 
[root@nginx ~]#           

案例:取基名和目录名

#取基名
[root@nginx ~]# echo "/etc/sysconfig/network-scripts/" |sed -r 's#(^/.*/)([^/]+/?)#\2#'
network-scripts/
[root@nginx ~]#

#取目录
[root@nginx ~]# echo "/etc/sysconfig/network-scripts/" |sed -r 's#(^/.*/)([^/]+/?)#\1#'
/etc/sysconfig/
[root@nginx ~]# 

#取目录名
[root@nginx ~]# echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\1#p'
/etc
[root@nginx ~]#

#取基名
[root@nginx ~]# echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\2#p'
sysconfig
[root@nginx ~]#           

案例: 取文件的前缀和后缀

[root@nginx ~]# echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\1/p'
a.b.c
[root@nginx ~]# echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\2/p'
gz
[root@nginx ~]# echo a.b.c.gz |grep -Eo '.*\.'
a.b.c.
[root@nginx ~]# echo a.b.c.gz |grep -Eo '[^.]+#39;
gz
[root@nginx ~]#           

案例:将非#开头的行加上#

[root@nginx ~]# sed -rn "s/^[^#]/#&/p" /etc/fstab
#/dev/mapper/centos-root /                       xfs     defaults        0 0
#UUID=d0727353-4fcc-4e63-802d-86f45ff1d3ad /boot                   xfs     defaults        0 0
#/dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@nginx ~]#

[root@nginx ~]# sed -rn 's/^[^#](.*)/#\1/p' /etc/fstab
#dev/mapper/centos-root /                       xfs     defaults        0 0
#UID=d0727353-4fcc-4e63-802d-86f45ff1d3ad /boot                   xfs     defaults        0 0
#dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@nginx ~]#

[root@nginx ~]# sed -rn '/^#/!s@^@#@p' /etc/fstab
#
#/dev/mapper/centos-root /                       xfs     defaults        0 0
#UUID=d0727353-4fcc-4e63-802d-86f45ff1d3ad /boot                   xfs     defaults        0 0
#/dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@nginx ~]#           

案例:将#开头的行删除#

[root@nginx ~]# sed -ri '/^#/s/^#//' /etc/fstab           

案例:查看配置文件

sed -r '/^(#|$)/d' /etc/etc/nginx/nginx.conf
sed -r '/^#|^$/d' /etc/etc/nginx/nginx.conf           

案例:引用变量

[root@nginx ~]# echo|sed "s/^/$RANDOM.rmvb/"
4834.rmvb
[root@nginx ~]# 
[root@nginx ~]# echo|sed 's/^/$RANDOM.rmvb/'
$RANDOM.rmvb
[root@nginx ~]#
[root@nginx ~]# echo|sed 's/^/'''$RANDOM'''.rmvb/'
9983.rmvb
[root@nginx ~]#           

1.2 sed 高级用法

sed 中除了模式空间,还另外还支持保持空间(Hold Space),利用此空间,可以将模式空间中的数据,临时保存至保持空间,从而后续接着处理,实现更为强大的功能。

常见的高级命令:

P :打印模式空间开端至\n内容,并追加到默认输出之前
h :把模式空间中的内容覆盖至保持空间中
H :把模式空间中的内容追加至保持空间中
g :从保持空间取出数据覆盖至模式空间
G :从保持空间取出内容追加至模式空间
x :把模式空间中的内容与保持空间中的内容进行互换
n :读取匹配到的行的下一行覆盖至模式空间
N :读取匹配到的行的下一行追加至模式空间
d :删除模式空间中的行
D :如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使
用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环           

练手格式:

sed -n 'n;p' FILE
seq 10 | sed 'N;s/\n//'
sed '1!G;h;$!d' FILE
sed  'N;D'FILE
seq 10 |sed  '3h;9G;9!d'
sed '$!N;$!D' FILE
sed '$!d' FILE
sed 'G' FILE
sed 'g' FILE
sed '/^$/d;G' FILE
sed 'n;d' FILE 
sed -n '1!G;h;$p' FILE           

shell脚本常用工具grep、sed 、awk 没事可以看看

敲完收工。。。。