1.sed简介
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如‘D’的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
功能:主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等
grep:单纯的文本查找匹配,无法对数据进行修改
sed:可以文本查找,也可以对文本编辑修改(替换、删除)
awk:格式化复杂的文本
格式:
1、sed [options] ‘command’ file(s) command=条件和处理动作,若command中包含变量,要用”command”
2、sed [options] -f scriptfile file(s)
常用选项:
-n:不输出模式空间内容到屏幕,即不自动打印
-e: 多点编辑
-f:/PATH/SCRIPT_FILE: 从指定文件中读取编辑脚本
-r: 支持使用扩展正则表达式
-i.bak: 备份文件并原处编辑
2.选项用法
准备文件:cp /etc/passwd /data/
1.-i:修改源文件,后面一定要接文件cat
[root@Centos7 data]#sed -i '2d' passwd
错误写法:
[root@Centos7_101 data]#cat -n passwd | sed -i '2d'
sed: no input files
2.-i.bak:修改源文件之前,备份以.bak结尾
[root@Centos7 data]#sed -i.bak '2d' passwd
-f:调用文本
[root@Centos7 data]#sed -r '/^[^#]/s/[[:alpha:]]/\u&/g' /etc/fstab
[root@Centos7 data]#vim sed.script
[root@Centos7 data]#cat sed.script
/^[^#]/s/[[:alpha:]]/\u&/g
[root@Centos7 data]#sed -r -f sed.script /etc/fstab
[root@Centos7 data]#cat sed.script
2s/.*inet //;s/ netmask.*//p
[root@Centos7 data]#ifconfig ens33 | sed -rnf sed.script
172.16.34.101
-e:多命令编辑
[root@Centos7_101 data]#ifconfig ens33 | sed -rne '2s/.* inet //p' -e 's/ netmask.*//p' -e 's/172/192/p'
172.20.34.101 netmask 255.255.0.0 broadcast 172.20.255.255 #这是第一条命令执行的结果
172.20.34.101 #这是在第一条结果的基础上执行后的结果
192.20.34.101 #这是在第2条结果基础上执行后的结果
等价于用;把命令隔开
[root@Centos7_101 data]#ifconfig ens33 | sed -rne '2s/.* inet //p;s/ netmask.*//p;s/172/192/p'
3.条件地址
- 表示全部打印在屏幕上
#sed -n ‘p’ passwd
2.打印指定行,打印第2行
[root@Centos7 data]#sed -n '2p' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@Centos7 data]#ifconfig ens33 | sed -n '2p'
inet 172.16.34.101 netmask 255.255.0.0 broadcast 172.16.255.255
3.显示最后一行
[root@Centos7 data]#sed -n '$p' passwd
chen:x:1000:1000:chen:/home/chen:/bin/bash
4.指定范围行,’1,3p’:第1到第3行
[root@Centos7 data]#sed -n '1,3p' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
5.正则表达匹配行,’/正则表达式/’,选项-r支持扩展正则表达式。
[root@Centos7 data]#sed -n '/^U/p' /etc/fstab 显示U开头的行
UUID=ba708318-e653-437f-b7e7-2c81ae7cbbe2 / xfs defaults 0 0
UUID=12984512-ec20-4b99-a000-34b8ba546a14 /boot xfs defaults 0 0
UUID=9c9b025f-487c-42cd-9bec-6f9c582cdbe5 /data xfs defaults 0 0
UUID=210c8f6a-8a2a-40cc-bd3b-6cb106159332 swap swap defaults 0 0
6.打印匹配/dev/sd,需要加转义符\/dev\/sd
[root@Centos7 data]#df -h | sed -n '/\/dev\/sd/p'
/dev/sda2 20G 4.0G 16G 20% /
/dev/sda5 27G 33M 27G 1% /data
/dev/sda1 1014M 165M 850M 17% /boot
7.打印第1行,和第1行后面的3行
[root@Centos7 data]#cat -n passwd | sed -n '1,+3p'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
8.从第3行开始,到以f开头的范围打印出来
#sed -n '3,/^f/p' passwd
9.匹配范围,’/正则表达式/,/正则表达式/’
10.打印奇数’1~2’和偶数’2~2’行,1~3,从1开始隔3个数
[root@Centos7 data]#seq 10|sed -n '1~2p'
1
3
5
7
9
[root@Centos7 data]#seq 10|sed -n '2~2p'
2
4
6
8
10
总结:条件大致分为:指定行、范围行、正则表达式、范围正则表达式、行加正则表达式
4.处理动作
编辑命令:
d: 删除模式空间匹配的行,并立即启用下一轮循环
p:打印当前模式空间内容,追加到默认输出之后
a []text:在指定行后面追加文本,支持使用\n实现多行追加
i []text:在行前面插入文本
c []text:替换行为单行或多行文本
w /path/somefile: 保存模式匹配的行至指定文件
r /path/somefile:读取指定文件的文本至模式空间中匹配到的行后
=: 为模式空间中的行打印行号
!:模式空间中匹配行取反处理
s///:查找替换,支持使用其它分隔符,s@@@,s###
替换标记:
g: 行内全局替换
p: 显示替换成功的行
w /PATH/TO/SOMEFILE:将替换成功的行保存至文件中
d:删除
1.删除指定行
[root@Centos7 data]#cat -n passwd | sed '2d'
1 root:x:0:0:root:/root:/bin/bash
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
……
[root@Centos7 data]#cat -n passwd | sed '2,20d'
1 root:x:0:0:root:/root:/bin/bash
21 gluster:x:995:992:GlusterFS daemons:/var/run/gluster:/sbin/nologin
[root@Centos7 data]#cat -n passwd | sed -n ‘2~2d;p’
命令解析:第一行是否满足’2~2d’,不满足,继续匹配下一条命令p,满足,然后打印到屏幕上
继续处理下一行,第二行满’2~2d’,满足,就删除,下一条命令就不用管了,继续依次执行后面行
把偶数行删掉,奇数行打印出来,等同:#sed -n ‘1~2p’
2.用正则表达式匹配到的行删掉
[root@Centos7 data]#sed '/^#/d' /etc/fstab
3.删除空白行
#sed '/^$/d' demo.txt
a:行后追加
1.指定行添加
[root@Centos7 data]#cat -n passwd | sed '1,20a new line'
1 root:x:0:0:root:/root:/bin/bash
new line
2 bin:x:1:1:bin:/bin:/sbin/nologin
new line
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
a后面加,告诉a,\后面的所有东西就是要追加的,包括空格
[root@Centos7 data]#cat -n passwd | sed '1,20a\ new line'
1 root:x:0:0:root:/root:/bin/bash
new line
2 bin:x:1:1:bin:/bin:/sbin/nologin
new line
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
new line
2.添加多行字符串间用\n换行即可
[root@Centos7 data]#cat -n passwd | sed '1,20a\ new line1\n new line2'
1 root:x:0:0:root:/root:/bin/bash
new line1
new line2
2 bin:x:1:1:bin:/bin:/sbin/nologin
new line1
new line2
3.匹配正则表达式
[root@Centos7 data]#sed '/^# Source .*/a\hello world' /root/.bashrc
i:前面行追加(语法和a同理)
c:满足条件行替换(语法和a同理)
[root@Centos7 data]#sed '/^# Source .*/c\ hello world' /root/.bashrc
w:满足条件行保存到指定文件
1.指定行
[root@Centos7 data]#cat -n passwd | sed -n '1,3w /data/f3'
[root@Centos7 data]#cat f3
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
2.正则表达式匹配行
[root@Centos7 data]#sed -n '/^U/w /data/f2' /etc/fstab
[root@Centos7 data]#cat f2
UUID=ba708318-e653-437f-b7e7-2c81ae7cbbe2 / xfs defaults 0 0
UUID=12984512-ec20-4b99-a000-34b8ba546a14 /boot xfs defaults 0 0
UUID=9c9b025f-487c-42cd-9bec-6f9c582cdbe5 /data xfs defaults 0 0
UUID=210c8f6a-8a2a-40cc-bd3b-6cb106159332 swap swap defaults 0 0
r:满足条件行后面添加指定文件内容
[root@Centos7 data]#cat addfile
cjx:x:222:2222:cjx:/sbin:/sbin/nologin
[root@Centos7 data]#cat passwd | sed '1r /data/addfile'
root:x:0:0:root:/root:/bin/bash
cjx:x:222:2222:cjx:/sbin:/sbin/nologin addfile内容添加到第1行后面
=:满足条件行前面行显示行号
[root@Centos7 data]#sed '1,3=' passwd
1
root:x:0:0:root:/root:/bin/bash
2
bin:x:1:1:bin:/bin:/sbin/nologin
3
!:取反显示行号,效果与=相反
s///:替换,达到增、删、改功能(重点)
#who am i | awk '{print $5}'|sed 's/[()]//g'
172.16.34.100
[root@Centos7 data]#sed 's/root/ROOT/' passwd
ROOT:x:0:0:root:/root:/bin/bash 只替换一个root
要想全局替换
[root@Centos7 data]#sed 's/root/ROOT/g' passwd
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
还可以指定第2个root,再开始替换
[root@Centos7 data]#sed 's/root/ROOT/2g' passwd
root:x:0:0:ROOT:/ROOT:/bin/bash
正则表达式分组:-r 表示支持扩展正则表达式 -n表示关掉默认打印,g表示全局替换,p表示满条件的打印出来
\1表示正则表达式的一个分组,分组后面加er
rooter:x:0:0:rooter:/rooter:/bin/bash
[root@Centos7 data]#sed -rn ‘s/(root)/\1er/gp’ passwd
operator:x:11:0:operator:/rooter:/sbin/nologin
例子1
[root@Centos7 data]#cat /etc/default/grub | sed -r 's/(quiet)/\1 net.ifnames=0/'
[root@Centos7 data]#cat /etc/default/grub | sed -r 's/(LINUX.*)"/\11 net.fnames=0"/'
还可以先查找满足条件的行,下例先用正则表达式匹配LINUX的行
[root@Centos7 data]#cat /etc/default/grub | sed -r '/LINUX/s/(.*)$"/\11 net.fnames=0"/'
[root@Centos7 data]#cat /etc/default/grub | sed -r '/LINUX/s/"$/ net.fnames=0"/'
例子2,用seq提取ip
[root@Centos7 data]#ifconfig ens33 | sed -n '2p'
inet 172.16.34.101 netmask 255.255.0.0 broadcast 172.16.255.255
方法1:把ip前后删掉,”;”可以添加多条命令
[root@Centos7 data]#ifconfig ens33 | sed -rn '2s/.*inet //;s/ netmask.*//p'
172.16.34.101
方法2:用分组实现
[root@Centos7 data]#ifconfig ens33 | sed -rn '2s/(.*inet )(.*)( netmask.*)/\2/p'
172.16.34.101
例子3:截取基名
[root@Centos7 data]#echo "/etc/sysconfig/network-scripts/" | sed -r 's#(^.*/)([^/]+/?)#\2#'
network-scripts/
截取目录名
#echo /etc/rc.d/init.d/functions | sed -rn 's#(/.*/)[[:alnum:]]+/?#\1#p'
例子4:非#开头的,加上#
[root@Centos7 data]#sed -r '/^[^#]/s/(.*)/#\1/' /etc/fstab
[root@Centos7 data]#sed -r '/^[^#]/s/(.*)/#&/' /etc/fstab
例子5:转成大写字母 \u:大写,\l:小写
[root@Centos7 data]#sed -r '/^[^#]/s/[[:alpha:]]/\u&/g' /etc/fstab
例子6:获取主版本号
[root@Centos7 data]#cat /etc/redhat-release | sed -r 's/(^.* )([[:digit:]]+)(.*)/\2/'
7
5.练习
sed示例
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 -n '/root/p;/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