使用sed代替vim修改文件内容
在写Shell脚本的时候,有时候要替换、删除某个文件中的内容,但是又不方便用vim做交互的动作,这就可以用到『sed』命令来做批量的替换、插入、删除
1.用法
sed [options] 'command' file(s)
# -f 将sed命令内容写在一个文件中,执行命令
sed -f scriptfile file(s)
# -i 直接对文件原地修改
sed -i 'command' file(s) # 默认sed只是通过内存临时修改文件,源文件无影响
常用选项(options):
-n∶使用安静(silent)模式。默认sed会输出读取文档的全部内容。但如果加上 -n 参数后,则只有经过sed特殊处理的那一行(或者动作)才会被列出来。
-e∶多点编辑 让一条sed可以执行多条指令
-f∶直接将 sed 的动作写在一个脚本文件内, -f filename 则可以执行 filename 内的sed动作;
-r∶让sed支持扩展正则 若与其它选项一起使用,应放作为首选项
-i∶直接修改读取的档案内容,而不是由屏幕输出。
常用命令(command):
a∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c∶替换, c 的后面可以接字串,这些字串可以取代n1,n2 之间的行!
d∶删除,因为是删除,所以 d后面通常不接任何内容
i∶插入, i的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p∶打印,就是将某个选择的资料显示。通常 p 会与参数 sed-n 一起运作
s∶替换,可以直接进行替换!通常这个 s的动作可以搭配正则表达式
2.部分示例
显示文件中的指定内容
# 显示file文件第一行
sed -n '1p' /path/to/file
# 显示file文件最后一行
sed -n '$p' /path/fo/file
# 显示file文件第1-2行
sed -n '1,2p' /pah/to/file
# 显示file文件第2到最后一行
sed -n '2,$p' abc.file
关键字模式查询
# 查询关键词包含test的所有行
sed -n '/test/p' /path/to/file
# 查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含义
sed -n '/\$/p' /path/to/file
删除文件中的内容
# 删除file文件的第2行
sed '2d'/path/to/file
# 删除file文件的第2行到末尾所有行
sed '2,$d' /path/to/file
# 删除file文件的最后一行
sed '$d' /path/to/file
# 删除file文件所有包含test的行
sed '/test/'d /path/to/file
对行进行插入
# 第一行后增加字符串"XXX"
sed '1a XXX' /path/to/file
# 第一行到第3行,每行后面都增加字符串"XXX"
sed '1,3a XXX' /path/to/file
# 在所有行后插入
sed 'a xxxx' nssw.txt
# 第二行前插入xxxx
sed '2i xxxx' nssw.txt
# 在所有行前插入xxxx
sed 'i xxxx' nssw.txt
对行进行替换
# 第一行代替为XXX
sed '1c XXX' /path/to/file
# 第一行到第2行代替为XXX
sed '1,2c XXX' /path/to/file
对行模式匹配替换
# 对一行内匹配到的字符都进行替换
sed 's/要被替换的字符串/新的字符串/g' filename # 在整行范围内把old替换为new
# 对一行内第一个匹配到的字符进行替换
sed 's/要被替换的字符串/新的字符串/' filename # 如果没有g标记,则只有每行第一个匹配的old被替换成new
# 删除一行内指定列的字符
sed 's/.//2' filename # 通过.匹配任意字符,然后将第二个匹配的字符替换为空,则删除了第二个字符
# 互换行内的字符位置
sed -r 's/^(.)(.*)(.)$/\3\2\1/' nssw.txt # 通过-r参数,扩展正则操作
# 范围内的行操作
sed '4,7s/^/#/' a.txt //将第4~7行注释掉(行首加#号)
注意:如果内容遇到/等特殊字符,那么sed里用到的/可以用冒号:或者#或者&代替
#替换的内容含有/,那么分隔符就用冒号,或者#号
sed 's:my.storageRoot=/storage:my.storageRoot=/home/storage:g' /opt/monitor/application.properties #示例中把my.storageRoot=/storage 修改成 my.storageRoot=/home/storage
保存修改文件
# 对替换内容后的文件,进行直接修改保存
sed -i 's/old/new/g' /path/to/file # 使用-i参数对文件进行直接修改
# 通过重定向符>进行保存,注意sed后没有-n参数
sed 's/old/new/g' /path/to/file > newfile_path # 使用>对文件进行直接修改
# 通过sed的-w参数进行保存,注意sed后有-n参数
sed -n '1,3w c.txt' a.txt # 把1到3行存储为新文件c.txt
sed -n '/^ii/w d.txt' a.txt # 把ii开头的行保存为d.txt
在Mac上执行上面有些命令可能会报错误,原因是mac强制要求备份,否则报错
解决方案,留一个空备份'':
只保留一份,不实用其他备份名字:
sed -i '' 's/Hello Tom/Hello World/g' test1.txt
3.特殊字符处理
shell脚本经常会使用替换操作,sed用处很广,下列集中对一些使用场景做出总结:
1. 普通操作可以使用冒号(:)井号(#)正斜杠(/)来作为分隔符
eg: sed -i 's#abc#def#g' geng.file ---将文件geng中的abc替换成def
cat geng.file | sed 's/abc/def/g' ---打印文件geng,并将其中的abc替换成def
2. 对于变量做替换
sed 若是单引号括起来的,变量上得再额外加个单引号才能引用生效;
若是双引号括起来的,可直接引用生效
eg: pa='127.0.0.1/32'; field='ip_allow=123'; \
echo $field | sed 's#^ip_allow=.*#ip_allow=${pa}#g'
结果:ip_allow=${pa} --变量替换未生效
echo $field | sed 's#^ip_allow=.*#ip_allow='${pa}'#g'
结果:ip_allow=127.0.0.1/32
echo $field | sed "s#^ip_allow=.*#ip_allow=${pa}#g"
结果:ip_allow=127.0.0.1/32
3. 特殊字符替换,反斜杠、正斜杠、双引号、$美元符
单个转义:多加个反斜杠做转义即可:反斜杠(\\)、正斜杠(\/)、双引号(\")
单转多个:参考如下列表
正斜杠(/)可以用单引号、双引号括起来进行替换;但是涉及到反斜杠(\)不行,不能用双引号,只能用单引号括起来替换,不然报错:sed: -e expression #1,char 8: unterminated `s' command
4. curl时用的变量,sed转化
curl -H 'Content-Type: application/json' -X POST -d 参数
(参数中涉及到特殊字符都得转义,而且要多转一层,即$得转成\\$,才能原封不动的供后续使用)
#值替换单引号、反斜杠、双引号 curl的时候用,多一层转义,所以\要用\\
sed -i "s#'#''#g" ${file} ---单引号要转成两个单引号
sed -i 's#\\#\\\\\\\\#g' ${file} ---反斜杠
sed -i "s:\":\\\\\":g" ${file} ---双引号
sed -i 's:\$:\\\\\$:g' ${file} ---美元符
curl引用参数的这种形式有两种写法:
1.直接引用单个参数变量
curl -H 'Content-Type: application/json' -X POST -d '{"type":"0","name":" ' ${pa_name} ' "}'
这种需要对变量额外加上一个单引号,才能引用生效!
2.整个参数变量作为一个整体(推荐)
param="{\"type\":\"0\", \"name\":\"${pa_name}\"}"
curl -H 'Content-Type: application/json' -X POST -d "${param}"