扫码阅读
手机扫码阅读

三剑客之 sed

127 2024-07-20

我们非常重视原创文章,为尊重知识产权并避免潜在的版权问题,我们在此提供文章的摘要供您初步了解。如果您想要查阅更为详尽的内容,访问作者的公众号页面获取完整文章。

查看原文:三剑客之 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/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/bashNO 2-5 NUMBERsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/noroot:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologin


2、将 root 替换成 noroot(全局替换)

sed -i 's/root/noroot/g' test.txt
noroot:x:0:0:noroot:/noroot:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/noroot:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/bashbin:x:1:1:bin:/bin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody: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/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinnewlinelp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologin


在当前行的上一行添加


使用 i 动作

1、在文件第四行的上一行添加 newline 字符串(即添加到第四行,原本第四行的内容变成了第五行)

sed -e '4i newline' test.txt
root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinnewlineadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologin


2、在文件第一行的上一行添加 newline 字符串(即添加到第一行,原本第一行的内容变成了第二行)

sed -e '1i newline' test.txt 
newlineroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologin

想要了解更多内容?

查看原文:三剑客之 sed
文章来源:
咸鱼运维杂谈
扫码关注公众号