shell文本处理三剑客之sed

sed 是 stream editor 的缩写,中文称之为“流编辑器”。

sed 命令是一个面向行处理的工具,它以“行”为处理单位,针对每一行进行处理,处理后的结果会输出到标准输出(STDOUT)。你会发现 sed 命令是很懂礼貌的一个命令,它不会对读取的文件做任何贸然的修改,而是将内容都输出到标准输出中。

格式

1
sed [option] '[pattern]/command' filename

除此之外,sed也支持管道符来传递引用文本

option参数

参数 含义
-e 多段编辑
-n 只打印出查询到的值
-f 可将某个文件作为patter传入
-r 支持扩展正则表达式
-i 修改源文件的内容

patter参数

参数 含义
10command 匹配第10行
10,20command 匹配从第10行到第20行
10,+5command 匹配从第10行开始,到第16行结束
/patter/command 匹配含有patter的行
/patter1/,/patter2/command 匹配到从含有patter1开始,到patter2结束的所有行
10,/patter/command 匹配从第10行开始,到含有patter的行结束的所有行
/patter/,10command 匹配从含有patter的行开始,到第10行结束的所有行

command参数

参数 含义
p 打印
a 行后增加
i 行前增加
r 外部文件读入,行后增加
w 将匹配到的行写入外部文件
d 删除
s/old/new 将行内的第1个old替换为new
s/old/new/g 将行内的所有old替换为new
s/old/new/2g 将行内的从第2处开始到结束的old替换为new
s/old/new/ig 将行内的所有old替换为new,且忽略大小写

反向引用

反向引用的意思是将前面匹配到的值通过参数的形式传递给后一个,可用&\1传递,例如:

1
2
sed -i 's/\(redis_Port=\).*/\15555/g' tmp.cfg	#修改redis的端口号为5555
#result:redis_Port=5555

值得注意的是,\1支持使用括号来指定反向引用的内容,而&并不支持这个功能

查询

参数 含义
1p 打印第1行的内容
1,10p 打印第1行到第10行的内容
1,+5p 打印第1行到第6行的内容
/patter/p 打印含有patter的行
/patter1/, /patter2/p 打印从含有patter1的行开始,到含有patter2的行结束
/patter/, 10p 打印从含有patter的行开始,到第10行结束
10,/patter/p 打印从第10行开始,到含有patter的行结束
1
2
3
4
5
6
# 查询包含redis的所有行
[srvc@vm-kvm5645-app ~]$ sed -n '/redis/p' tmp.cfg
redis_Port=5555
redis_Timeout=1
redis_PORT_ALARM=6379
redis_TIMEOUT_ALARM=5

修改

参数 含义
1s/old/new/ 替换第一行的old为new
1,10s/old/new/ 将1到10行中的old替换为new
1, +5s/old/new/ 将1到6行中的old替换为new
/patter/s/old/new/ 将含有patter的行中的old替换为new
/patter1/,/patter2/s/old/new/ 将从含有patter1开始的行到patter2结束行中的old替换为new
/patter/,10s/old/new/ 将从patter开始的行到第10行结束的old替换为new
10,/patter/s/old/new/ 将从第10行开始到含有patter行结束的old替换为new
1
2
# 将redis的超时时间修改为3s
sed -i '/\[.*\]/,/\[.*\]/s/\(redis_Timeout=\).*/\13/g' tmp.cfg

删除

参数 含义
1d 删除第1行的内容
1,10d 删除第1行到第10行的内容
1,+5d 删除第1行到第6行内容
/patter/d 删除含有patter的行
/patter1/,/patter2/d 删除从包含patter1的行开始,到包含patter2结束的所有行
/patter/, 10d 删除从包含patter的行开始,到第10行结束的所有行
10,/patter/d 删除从第10行开始,到含有patter的行结束的所有行
1
2
# 删除配置文件中的注释行和空行
sed -i '/^#/d;/^$/d' tmp.cfg

shell脚本

对于自动化测试来说,shell脚本的存在价值似乎并没有太大必要,而且由于公司使用的是python来作为自动化编程语言,问题在于,使用RF执行python脚本修改服务器上配置文件时,老是会出错,且通过beyond compares对比,修改之后有问题的文件和之前正确的文件无任何差别,初步判断有可能是编码问题,由于公司的RF必须使用jybot来执行脚本,于是,为了不纠结这个问题,使用shell脚本处理

1
2
3
4
5
6
7
8
9
10
11
12
[srvc@vm-kvm5645-app auto_test]$ more modify_wf.sh
#/bin/bash
#
#author:tangxiao
#modify redis password or host in WEATHER.cfg

function modify
{
sed -i "/\#weather_open/,/redis_Timeout/ s/$1/$2/g" /opt/app/todewf/bin/WEATHER.cfg
}

modify $1 $2

需要注意的点是,由于引用了变量$1$2,patter部分语句必须使用双引号,且执行脚本的时候,传入的参数必须使用引号

1
sh modify_wf.sh '\(redis_Pass=\).*' '\1${redis_pass}'

参考:

-------------本文结束感谢您的阅读-------------