导言:
笔者之前花了较多时间学习并整理了sed命令相关的内容,以及一些进阶内容。但是,到后来使用也就只记得那么几个简单的选项,再高级的方法有点记不住,所以感觉当时耗费的时间和精力有点得不偿失。这次笔者只整理一些日常运维中常用的选项和参数,遇到比较困难实现的时候可以考虑查阅资料或者用其他语言哦。
比较详细的资料,可以参考
SECTION 23 sed编辑器基础
SECTION 25 sed进阶(一)
SECTION 26 sed进阶(二)
【BASH】回顾与知识点梳理(八)
1 sed 介绍
sed编辑器称为流编辑器(stream editor
),会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。sed编辑器根据命令来处理数据流中的数据,这些命令要么从命令行输入,要么存储在命令文本文件中
sed编辑器会执行下列操作:
1.一次从输入中读取一行数据
2.根据所提供的编辑器命令匹配数据
3.按照命令修改流中的数据
4.将新的数据输出到STDOUT
语法
SYNOPSIS
sed [OPTION]... {script-only-if-no-other-script} [input-file]...
sed [options] {sed-commands} [input-file]...
- 常用选项(
OPTION
)
选项 | 说明 |
---|---|
-n | 只输出匹配行 |
-i | 直接修改文件内容(谨慎使用) |
-r | 支持扩展正则表达式 |
-e | 执行多条sed命令, 分号隔开 |
-f | 把所有脚本放到一个script文件里使用(不常用) |
- 常用命令(
COMMAND
)
命令 | 说明 |
---|---|
s | sub,替换 |
p | print,输出,打印 |
d | del,删除 |
cai | c,replace 替换,c 替换指定行,而s 替换匹配内容a,append 追加 i,insert,插入 |
- 常用标记
标记 | 说明 |
---|---|
g | 表示行内全面替换 |
p | 表示打印行 |
\1 | 第一个子串匹配标记,类似第二个\2 ,第三个\3 … |
& | 已匹配字符串标记 |
我们提前准备一个文件用于示例展示
[root@node-252 ~]# cat -n sed.txt
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 230.heilongj.haerbin
5 310.shanghai.shanghai
6 320.jiangsu.nanjing
7 330.zhejiang.hangzhou
8 370.shandong.jinan
2 查找
基本格式
sed -n '***p' sed.txt
按行查找,第2行
[root@node-252 ~]# sed -n '2p' sed.txt
210.liaoning.shenyang
按行的范围查找,第2到5行
[root@node-252 ~]# sed -n '2,5p' sed.txt
210.liaoning.shenyang
220.jilin.changchun
230.heilongj.haerbin
310.shanghai.shanghai
按匹配模式查找
[root@node-252 ~]# sed -n '/heilongj/p' sed.txt
230.heilongj.haerbin
按匹配模式范围查找
[root@node-252 ~]# sed -n '/heilongj/,/jiangsu/p' sed.txt
230.heilongj.haerbin
310.shanghai.shanghai
320.jiangsu.nanjing
使用扩展正则表达式匹配多个记录,因为要使用扩展正字符|
,则此时需要加-r
[root@node-252 ~]# sed -rn '/liaoning|jiangsu/p' sed.txt
210.liaoning.shenyang
320.jiangsu.nanjing
在标记位加I
能够不区分大小写匹配
[root@node-252 ~]# sed -n '/JIANGSU/Ip' sed.txt
320.jiangsu.nanjing
3 替换
基本格式
sed 's/*/*/p' sed.txt
这里的/
可以替换为#
,$
等其他符号,但需要一致,这是因为当匹配内容中包含/
的时候,为避免使用转义符提供便利
替换匹配内容
[root@node-252 ~]# sed 's/shenyang/dalian/g' sed.txt
110.beijing.beijing
210.liaoning.dalian ==>此处替换
220.jilin.changchun
230.heilongj.haerbin
310.shanghai.shanghai
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
替换匹配内容,并仅显示替换的行
[root@node-252 ~]# sed -n 's/10/1000/gp' sed.txt
11000.beijing.beijing
21000.liaoning.shenyang
31000.shanghai.shanghai
替换匹配内容,并修改文件
[root@node-252 ~]# sed -i 's/shenyang/dalian/g' sed.txt
[root@node-252 ~]# cat -n sed.txt
1 110.beijing.beijing
2 210.liaoning.dalian
3 220.jilin.changchun
4 230.heilongj.haerbin
5 310.shanghai.shanghai
6 320.jiangsu.nanjing
7 330.zhejiang.hangzhou
8 370.shandong.jinan
这个应该是运维中sed用的最多的方式了,注意这个修改有一定危险程度,使用需谨慎
但是这个有个进阶的使用方式,如下
替换匹配内容,修改文件,并在修改前备份原文件
[root@node-252 ~]# sed -i.bak 's/dalian/shenyang/g' sed.txt
[root@node-252 ~]# cat sed.txt
110.beijing.beijing
210.liaoning.shenyang
220.jilin.changchun
230.heilongj.haerbin
310.shanghai.shanghai
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
[root@node-252 ~]# cat sed.txt.bak
110.beijing.beijing
210.liaoning.dalian
220.jilin.changchun
230.heilongj.haerbin
310.shanghai.shanghai
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
在替换文件内容之前会把原文件加后缀名.bak
进行备份,当然如果您指定其他后缀名称也是可以的,.bak
只是更为直观的体现该文件作用
替换还有一个隐藏功能是删除
[root@node-252 ~]# sed -n 's/dalian//gp' sed.txt.bak
210.liaoning.
4 反向引用
它允许你捕获一部分表达式,然后在同一个模式空间中的其他地方重复使用这部分表达式。反向引用的语法是:\1, \2, \3, ..., \9
,对应到前面的相应的捕获组(capture group)。
由于反向引用需要使用()
,所以此时我们需要使用选项-r
#210.liaoning.shenyang 匹配行
[root@node-252 ~]# sed -rn 's#(.*).liaoning.(.*)#\1,\2#gp' sed.txt
210,shenyang
使用&
可以表示前面所有的匹配内容
[root@node-252 ~]# echo '123456'| sed -r 's#(.*)#++++&++++#g'
++++123456++++
示例
反向引用可以干什么?举个简单的例子,要求把/etc/passwd
中的用户名和命令解释器进行调换,即
[root@node-252 ~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
#改为
/bin/bash:x:0:0:root:/root:root
怎么做呢?
[root@node-252 ~]# sed -r 's#(.*)(:x.*:)(.*)#\3\2\1#g' /etc/passwd
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
...
这里子串\2
之所以能匹配成功,也是利用了正则表达式的贪婪性
5 删除
这部分和查找
的使用方式基本类似,可能最大的区别是p
换成了d
[root@node-252 ~]# cat -n sed.txt
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 230.heilongj.haerbin
5 310.shanghai.shanghai
6 320.jiangsu.nanjing
7 330.zhejiang.hangzhou
8 370.shandong.jinan
删除指定行
[root@node-252 ~]# sed '3d' sed.txt
110.beijing.beijing
210.liaoning.shenyang
230.heilongj.haerbin
310.shanghai.shanghai
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
删除指定范围行
[root@node-252 ~]# sed '3,5d' sed.txt
110.beijing.beijing
210.liaoning.shenyang
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
删除匹配行
[root@node-252 ~]# sed -r '/heilongj/d' sed.txt
110.beijing.beijing
210.liaoning.shenyang
220.jilin.changchun
310.shanghai.shanghai
320.jiangsu.nanjing
330.zhejiang.hangzhou
370.shandong.jinan
删除匹配范围行
[root@node-252 ~]# sed -r '/heilongj/,/jiangsu/d' sed.txt
110.beijing.beijing
210.liaoning.shenyang
220.jilin.changchun
330.zhejiang.hangzhou
370.shandong.jinan
6 cai(菜)
由于c
、a
和i
使用方法基本类似,都是针对行进行操作,所以放在一起说明了
c
replace,替换匹配行整行a
append,在匹配行后追加i
insert,在匹配行前增加
基本格式
sed '[address]command\newline' [file]
反斜线\
可以换成空格' '
[root@node-252 ~]# cat -n sed.txt
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 230.heilongj.haerbin
5 310.shanghai.shanghai
6 320.jiangsu.nanjing
7 330.zhejiang.hangzhou
8 370.shandong.jinan
[root@node-252 ~]# sed '4c abcdefg' sed.txt|cat -n
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 abcdefg
5 310.shanghai.shanghai
6 320.jiangsu.nanjing
7 330.zhejiang.hangzhou
8 370.shandong.jinan
[root@node-252 ~]# sed '4a abcdefg' sed.txt|cat -n
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 230.heilongj.haerbin
5 abcdefg
6 310.shanghai.shanghai
7 320.jiangsu.nanjing
8 330.zhejiang.hangzhou
9 370.shandong.jinan
[root@node-252 ~]# sed '4i abcdefg' sed.txt|cat -n
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 abcdefg
5 230.heilongj.haerbin
6 310.shanghai.shanghai
7 320.jiangsu.nanjing
8 330.zhejiang.hangzhou
9 370.shandong.jinan
匹配模式
[root@node-252 ~]# sed '/heilongj/i abcdefg' sed.txt|cat -n
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 abcdefg
5 230.heilongj.haerbin
6 310.shanghai.shanghai
7 320.jiangsu.nanjing
8 330.zhejiang.hangzhou
9 370.shandong.jinan
范围匹配
[root@node-252 ~]# sed '/heilongj/,/jiangsu/i abcdefg' sed.txt|cat -n
1 110.beijing.beijing
2 210.liaoning.shenyang
3 220.jilin.changchun
4 abcdefg
5 230.heilongj.haerbin
6 abcdefg
7 310.shanghai.shanghai
8 abcdefg
9 320.jiangsu.nanjing
10 330.zhejiang.hangzhou
11 370.shandong.jinan
注意:每行前面都会插入字符串,这并不常用
最后我们以一个小练习结束本文,分别使用grep
,sed
和awk
分别过滤出本机IP地址
[root@node-252 ~]# ip a s ens33|grep -E -o 'inet (.*)/'|grep -E -o '([0-9]{1,3}\.){3}[0-9]{1,3}'
192.168.202.128
[root@node-252 ~]# ip a s ens33|sed -n '3p'|sed -r 's#^.*inet (.*)/.*$#\1#g'
192.168.202.128
[root@node-252 ~]# ip a s ens33|awk 'NR==3 {print $2}'|awk -F/ '{print $1}'
192.168.202.128