在Linux中,一般存在两种文本编辑器,即交互式编辑器和流编辑器,交互式编辑器就是交互式的添加、删除、更改文件内容,我们常用的vi、vim、gedit就是交互式编辑器,而流编辑器则是按照预先定义好的操作规则对文本文件进行添加、删除、更改等操作,今天我们就来讲流编辑器sed。
sed流编辑器是以行为单位进行文本处理的,其基本语法格式如下:
sed [选项] '命令' 文件
sed [选项] -f 脚本文件 文件
说明:以上展示了sed的两种使用方式,目标文件可以是一个文件或多个文件,第一种使用sed内置的命令进行目标文本文件的操作,使用命令可以实现文本的各种操作,但命令要使用单引号括起来;第二种是使用定义好的脚本对目标文件进行操作;
注意:sed是以行为单位的,也就是说,sed会读入目标文件的一行,然后与命令进行匹配,匹配成功则进行对应的操作,然后处理完后继续读入下一行,直到处理完数据流中的全部数据行才停止工作。
sed [选项] [sed内置的命令] [文件]
最常用的[选项]有下面这些:
-n :默认情况下即使不匹配,sed也会输出不匹配的行,而使用-n可以禁止打印模式空间的不匹配的数据,一般与p连用,表示匹配命令后才明确打印模式空间的数据,如:sed -n '3p' testsed.tex ,如:sed -n '1s:g:GG:gp' testsed.tex,表示对第一行进行全局搜索并进行字符替换后定义改行,如果不加p,则所有的行都被输出,即使只指定第一行是处理行,即使其他行没有被处理过。
-e :连接多个编辑命令,如:sed -e 's/g/G/g' -e 's/b/B/g' testsed.tex
-i :直接将修改结果写回到源文件,如果不用-i,那么sed修改的只是它模式空间内存的数据
-r :支持正则扩展
-f:指定包含编辑命令的文件,因为sed的编辑命令可以放在一个单独的文件中,当要使用时直接用-f包含过来即可,如:sed -f file.sed testsed.tex
sed的内置命令
用于对文件的不同操作,如对文件的增删改查:
i insert,表示插入文本,在匹配行的前面插入文本
a append,对文件的追加,值指定行后面追加一行或多行的文本
c 用此符号后的新文本替换当前行中的文本
d delete,删除匹配的行
p print,打印匹配的行,一般与选项-n一起使用
s/正则/替换的内容/g 匹配正则表达式,然后替换内容,结尾的g表示全局匹配,s替换命令默认只会替换一行中的第一个匹配的字符串,除非指定全局替换字符g
r 从文件中读取输入行
w 将所选的行写入文件
可以指定第几行,使用地址定位来实现,如下:
x 表示指定第x行
x,y 表示x到y行
/key/ 表示查询包含关键字key的行
/key1/,/key2/ 表示匹配包含两个关键字之间的行
/key/,x 从匹配关键字开始到文件第x行
x, /key/ 从第x行开始到与关键字的匹配行之间的行
x,y! 不包含x到y行
演示示例:
# sed的打印输出
#输入test.txt 文件的2到5行,-n表示不匹配的不要输出,匹配的才输出,p表示打印
sed -n '2p' text.txt #打印第2行
sed -n '2p,5p' text.txt #打印第2行和第5行
sed -n '2,5p' text.txt #打印第2到第5行
sed -n '1!p' text.txt #打印除第1行之外的其他行
sed -n '/nologin$/p' text.txt #打印以nologin结尾的行
# sed查找字符并打印输出字符的行
sed -n '/disabled/p' /etc/selinux/config #在两个分割符之间写要匹配的disabled字符
sed -n '/root/p' test.txt #查找root的行并打印输出
# sed删除包含字符的行
#-i表示将修改结果写回到源文件,如果不用-i,那么sed修改的只是它模式空间内存的数据,文件并没有改变,所以需要使用-i参数
# d 表示delete,删除匹配的行
sed -i '/systemd/d' text.txt #删除有systemd的行
sed -i '1,6503d' text.ttx #删除第1行到第6503行
sed -i '1d;6d' text.ttx #删除第1行和第6行
sed -i '5,$d' test.txt #删除第5行到末尾行
```bash
# sed插入字符
# i表示insert插入,是在行前面插入,a表示append追加,是在行末尾追加
sed -i '1iI am guo' text.txt #在第1行前面插入I am guo
sed -i '4aI am guo' text.txt #在第4行后面插入I am guo
sed -i '1iI am guo.\nGood man' text.txt #在第1行前面插入I am guo,然后换行后插入了Good man
sed -i '4iI am fullsh;6aI am good man' text.txt #错误的,在第4行前面插入I am fullsh,在第6行后面插入I am good man (不行)
sed -i -e '4iI am fullsh' -e '6aI am good man' text.txt #正确的,在第4行前面插入I am fullsh,在第6行后面插入I am good man (正确的)
sed -i '4,6iI am good man' text.txt #在第4行到第6行的行的前面插入I am good man
sed -i 'ihello world' text.txt #每一行(没有指定数字就是每一行)的前面插入hello world
sed -i 'aI am guo,I am good man.' text.txt #在每一行(没有指定数字就是每一行)后面添加一行I am guo,I am good man.
sed -i '$ihello world' text.txt #在最后一行的前面插入字符串hello world
sed -i '$ahello world' text.txt #在最后一行的后面插入字符串hello world
sed '2cI am good man' text.txt #c表示使用字符替换整行,使用I am good man替换第2行
sed '2r /home/file.txt' text.txt #r表示从文件读取行,从/home/file.txt文件读取行插入text.txt的第2行后面
sed '$r /home/file.txt' text.txt #从/home/file.txt文件读取行插入text.txt的最后面
sed '1,5w /home/file.txt' text.txt #w表示写入文件,表示将text.txt中的第1行到第5行覆盖到/home/file.txt中
# sed 的替换
# -i表示将修改结果写回到源文件,如果不用-i,那么sed修改的只是它模式空间内存的数据,文件并没有改变,所以需要使用-i参数
# s/正则/替换的内容/g 匹配正则表达式,然后替换内容,结尾的g表示全局匹配,s替换命令默认只会替换一行中的第一个匹配的字符串,除非指定全局替换字符g
sed -i 's/daemon/GOOD/g' test.txt # 将全部的daemon替换为GOOD
sed -i 's#daemon#GOOD#g' test.txt # 分隔符其实可以使用#号,此条等价于上面一条
sed -ri 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config #常用,-r表示支持正则表达式
sed -i 's/nologin/login/g;s/ceph/CEPH/g' text.txt #将全局的nologin替换为login,ceph替换为CEPH
# sed 使用 -e 连接多条命令
# 将全部的daemon替换为DAEMON,同时也将全部的nologin替换为NOLOGIN
# -e :连接多个编辑命令,-i表示写回源文件,g表示全局替换
# 要使用2个-e参数
sed -i -e 's/daemon/DAEMON/g' -e 's/nologin/NOLOGIN/g' test.txt
正则:
sed -i 's/^root/#&/' text.txt #注释掉以root开头的行
sed -rn '/^rpc|^mail/p' text.txt #打印rpc开头或mail开头的行
sed -rn '/false$/p' text.txt #打印false结尾的行