三剑客之 sed
本篇文章参考文献:
sed, a stream editor (gnu.org)
https://www.gnu.org/software/sed/manual/sed.html
awk 于1977年出生,今年45岁,sed 比 awk 大 2-3 岁(比我大23岁...)
sed 全名叫 stream editor,流编辑器,用程序的方式来编辑文本
今天这篇文章主要目的还是为了引起大家对 sed 的兴趣,对于这个上古神器还需要大家自行去查阅相关文档去进一步学习
废话少说,开始今天的 sed 学习之旅吧!
sed 语法:
sed [-nefr] [动作]
-n
只输出匹配到的内容
-e
直接在命令行上进行 sed 的动作
-f
将执行 sed 后的结果重定向到一个文件里,f filename 则可以执行 filename 內的 sed 动作
-r
支持扩展正则表达式
-i
对文件直接修改,而不是只输出到屏幕
替换(s,c)
替换一般涉及到文本内容修改,需要加上 -i 动作
以 test.txt 为例子
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
以行为单位的替换
1、将 2 到 5 行的内容替换成 ”NO 2-5 NUMBER“
sed -i '2,5c NO 2-5 NUMBER' test.txt
root:x:0:0:root:/root:/bin/bash
NO 2-5 NUMBER
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
以字符串为单位的替换
sed 's/要被取代的字串/新的字串/g
PS:加上 p 是指全部替换,不加的话只对第一个匹配到的字符串进行替换,后续的不进行替换
1、将 root 替换成 noroot(非全局替换)
sed -i 's/root/noroot/' test.txt
可以看到只替换了第一个匹配到的 root
noroot:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/noroot:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
2、将 root 替换成 noroot(全局替换)
sed -i 's/root/noroot/g' test.txt
noroot:x:0:0:noroot:/noroot:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/noroot:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
3、替换路径
有些内容(比如说文件路径)会有 "/" 符号,这时候我们就需要转义符避免系统识别错误
例如下面一段内容(path.txt):
/var/log/app1/app1.log
我们需要将路径中的 /root/log/app1/app1.log 替换成 /home/log/app1/app1.log
方法一:多次替换
sed -i -e 's/app1/app2/g' -e 's/root/home/g' path.txt
方法二:使用 # 作为分隔符
这样可以避免转义问题
sed -i -e 's#/root/log/app1/app1.log#/home/log/app2/app2.log#' path.txt
方法三:直接使用转义字符(这个看着比较晦涩,个人建议使用方法2)
sed -i -e 's/\/root\/log\/app1\/app1.log/\/home\/log\/app2\/app2.log/' path.txt
4、将文本中的 Windows 换行符替换成 UNIX 换行符
我们知道,windows 系统的换行符跟 Linux 系统(Unix类系统)的换行符是不一致的
Unix 系统里,每行结尾只有 “<换行>”,即 “\n”;Windows 系统里面,每行结尾是“ <回车><换行>”,即“\r\n”
一个直接后果是,Unix 系统下的文件在 Windows 里打开的话,所有文字会变成一行
而 Windows 里的文件在 Unix 下打开的话,在每行的结尾可能会多出一个 ^M 符号
而我们一般习惯在 windows 系统上面编写脚本编写配置文件再复制粘贴到 Linux
系统上去,如果换行符不对,就极有可能导致出错
所以我们需要将 windows 的换行符替换成 Linux 的换行符
对文件进行 sed 操作(^M 这么敲:Ctrl+v,Ctrl+m)
sed -i 's/^M//g' myfile
打印(p)
你可以把这个命令当成grep式的命令
涉及到打印的操作,一般与 -n 参数 搭配
如果不加参数,会是这种效果
sed '/daemon/p' test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
加了 -n 参数,就仅仅只把匹配到的内容输出出来
sed -n '/daemon/p' test.txt
daemon:x:2:2:daemon:/sbin:/sbin/nologin
删除(d)
删除匹配到的所在行
不会加 -n ,加了就什么都不输出了
1、删除 daemon 所在行
sed '/daemon/d' test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
2、删除 daemon 和 root 所在行
sed -e '/daemon/d' -e /root/d test.txt
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
添加(a,i)
在当前行的下一行添加
使用 a 动作
1、在文件第四行的下一行添加 newline 字符串(即添加到第五行
sed -e '4a\newline' test.txt
sed -e '4a newline' test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
newline
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
在当前行的上一行添加
使用 i 动作
1、在文件第四行的上一行添加 newline 字符串(即添加到第四行,原本第四行的内容变成了第五行)
sed -e '4i newline' test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
newline
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
2、在文件第一行的上一行添加 newline 字符串(即添加到第一行,原本第一行的内容变成了第二行)
sed -e '1i newline' test.txt
newline
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin