Linux 三剑客之 sed 流式文本编辑
三剑客里 grep 管找、awk 管算,改文本这活儿归 sed。它是个流式编辑器,不打开文件就能按行替换、删除、插入。这篇先理清三剑客分工,再重点拆 sed 的替换、行操作、常用参数和几个实战套路。
上一篇聊完了 grep,今天接着说三剑客里的第二位:sed。
如果说 grep 是负责“找”的,那 sed 就是负责“改”的那个。
我早年改配置文件、批量替换字符串,都是手动打开文件一个个改,费劲还容易漏。后来学会了 sed,一行命令搞定,才知道之前是在给自己找罪受。
这篇先把三剑客的分工再过一遍,然后重点把 sed 拆开讲。
三剑客各自干啥
还是先给个整体印象,三个命令各管一摊。
- grep:负责找。从文本里把符合条件的行捞出来,只筛选不改内容。
- sed:负责改。流式编辑器,按行做替换、删除、插入,专门改文本内容。
- awk:负责算。把每行按列切开,取字段、做统计、搞运算,处理结构化文本最强。
同样一份日志摆面前:
- 挑出所有报错的行 → grep
- 把里面的旧域名批量换成新域名 → sed
- 统计每个接口调用了多少次 → awk
今天主角是 sed,那位管“改”的。
sed 是个什么东西
sed 全称 stream editor,流式编辑器。
“流式”这个词是理解 sed 的钥匙。
它不像你平时用编辑器那样把整个文件加载进来改。它是一行一行地读、一行一行地处理、一行一行地吐出来,像水流一样过一遍。
所以处理超大文件它也不怵,不会把内存撑爆。
基础格式长这样:
# sed '处理动作' 文件名
sed 's/old/new/' file.txt
注意一个关键点:sed 默认不改原文件,它只是把处理后的结果打印到屏幕上。
这其实是个很贴心的设计,让你先看看效果对不对,确认没问题了再决定要不要落地。
我个人特别吃这一套,改之前先干跑一遍看结果,稳。
替换是 sed 的看家本领
sed 用得最多的就是替换,也就是那个 s 命令(substitute)。
格式是 s/要替换的/替换成的/。
# 把每行第一个 laowang 换成 mebugs
sed 's/laowang/mebugs/' users.txt
跑一下你会发现,它只替换了每行第一个匹配的。如果一行里有好几个 laowang,后面的没动。
想全部替换,末尾加个 g(global,全局):
# 一行里所有的 laowang 都换掉
sed 's/laowang/mebugs/g' users.txt
这个 g 忘了加是新手最常踩的坑,明明命令没错,结果只换了一半,找半天原因。
指定分隔符
替换的内容里如果带斜杠,比如换路径,再用 / 当分隔符就得一堆转义,很难看:
# 又是转义又是斜杠,眼睛都花了
sed 's/\/usr\/local/\/opt/g' path.txt
sed 允许你换分隔符,s 后面第一个字符是啥,它就拿啥当分隔符。换成 # 或者 | 清爽多了:
# 用 # 当分隔符,路径里的 / 不用转义了
sed 's#/usr/local#/opt#g' path.txt
换路径、换 URL 的时候,这招能救命。
按行动手
sed 不光能替换,还能对整行下手:删除、打印、指定行操作。
只处理某些行
在命令前面加行号,就只对那些行生效:
# 只把第 3 行的 laowang 换成 mebugs
sed '3s/laowang/mebugs/' users.txt
# 只处理第 2 到第 5 行
sed '2,5s/error/ERROR/g' app.log
2,5 就是第 2 到 5 行这个范围。
删除行
d 命令(delete)删行,配合行号或范围用:
# 删掉第 1 行(比如去掉表头)
sed '1d' data.csv
# 删掉所有空行
sed '/^$/d' app.log
# 删掉包含 DEBUG 的行
sed '/DEBUG/d' app.log
那个 /^$/d 删空行我用得贼多,很多文本清洗第一步就是先把空行干掉。
这里的 /DEBUG/ 是地址匹配,意思是“凡是匹配这个模式的行”,然后对它执行后面的 d。
打印指定行
p 命令(print)打印行。不过它默认会连原来的输出一起打,得配合 -n 用:
# -n 关掉默认输出,p 只打第 10 到 20 行,效果类似 sed 版的 head/tail
sed -n '10,20p' app.log
想从大文件里精确掏某一段出来看,这个组合比 head 接 tail 直观。
几个常用参数
sed 参数不多,但有两个绕不开。
-n 关掉默认输出
前面提过了。sed 默认每处理完一行都会打印出来,-n 把这个默认行为关掉,让你用 p 精确控制打印什么。
-i 直接改原文件
前面说 sed 默认不动原文件。真想落地改,加 -i(in-place):
# 直接把 config.txt 里的旧域名改掉,文件真的变了
sed -i 's/old.com/new.com/g' config.txt
这个参数要慎用。加了 -i 就是真改,改错了没有后悔药。
我的习惯是:先不带 -i 干跑一遍,肉眼确认结果对了,再加 -i 落地。或者稳妥点,用 -i.bak 让它顺手备份一份:
# 改的同时生成一个 config.txt.bak 备份,改砸了还能找回来
sed -i.bak 's/old.com/new.com/g' config.txt
这个 .bak 备份救过我不止一次,强烈建议养成习惯。
-E 用扩展正则
跟 grep 一样,sed 的基础正则里 +、?、| 要转义,加 -E 就能直接用扩展正则,写着舒服。
# 把 error 或 warn 开头的行标记一下
sed -E 's/^(error|warn)/[LOG] &/' app.log
这里的 & 是个彩蛋:它代表刚刚匹配到的整段内容。上面这行就是在匹配到的东西前面加个 [LOG] 标签,原内容靠 & 原样带出来。
串起来的实战套路
单个命令说完,看几个组合的真实用法。
配合管道加工输出
sed 能接在管道后面,处理别的命令的输出:
# 查进程,顺手把多余的空格压成一个,看着整齐
ps -ef | grep nginx | sed 's/ */ /g'
批量改多个文件
配合通配符或者 find,一次改一堆文件:
# 把当前目录所有 .conf 文件里的旧端口批量改掉,各自备份
sed -i.bak 's/8080/9090/g' *.conf
批量替换配置这种活儿,交给 sed 一行搞定,手动改十个文件的日子一去不返。
删注释和空行
看一份配置文件,注释和空行一大堆,只想看真正生效的配置:
# 先删掉 # 开头的注释行,再删空行,剩下的才是干货
sed -e '/^#/d' -e '/^$/d' nginx.conf
-e 可以串多个动作,一条命令里连着执行。看配置文件真身的时候特别爽。
小结
sed 这一趟走下来,核心其实就围着“改”字转。
三剑客的分工还是那句话:grep 找、sed 改、awk 算。
sed 自己的要点:
- 它是流式编辑器,一行行过,默认不改原文件只打印结果
- 看家本领是替换
s/old/new/,全局替换记得加g - 行操作有删除
d、打印p,配合行号或/模式/地址匹配 - 真要落地改文件用
-i,强烈建议配-i.bak顺手备份 - 用到
|、+就上-E,&能引用匹配到的整段内容
sed 比 grep 稍微绕一点,但替换和批量改文本的场景实在太常见,值得花时间练熟。
三剑客还剩最后一位 awk,那位是搞“算”的,最硬核,留到下一篇再啃。
那就拿 sed 先改起来吧。
