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 先改起来吧。

更多推荐

章节目录