之前我接手过一批几十台的缓存节点,统一要改Nginx里的一个限流参数,有人提议写个Python脚本批量下发,有人建议用Ansible。那边临时环境连外网拉包都不方便,最后我在命令行里敲下一条长度不到100字符的sed命令,几秒钟内把所有节点配置全部改完,原地验证无误。那个场景给我留下的印象太深了:Linux系统里预装的命令,sed绝对是被低估的一个。
这篇文章正想系统讲讲sed命令。它不是一本命令手册的翻译,而是我从日常使用里提炼出来的实践笔记,重点覆盖“增删查改”四条主干,以及那些文档里很少写但实际开发运维中极易遇到的行为陷阱。无论你是刚学Linux常用命令的新手,还是需要经常处理服务器配置文件的运维,这篇文章应该能让你少走很多弯路。
1. 为什么处理文本流时,我最先挑中的是sed
1.1 sed不是又一个编辑器,而是编辑器里最像流水线的一层
很多人一听到sed,就把它归类成“另一个命令”,然后背了些参数就扔在一边,真遇到任务还是打开vim老老实实写宏。这种用法并不是错的,只是没有把sed最擅长的场景用起来。
sed的全名是stream editor,直译过来就是流编辑器。关键点落在“流”上:它处理的对象不是文件本身,而是从文件或管道中源源不断流入的文本行。这对Linux这种“一切皆文件、一切皆数据流”的系统来说,位置非常特殊。vim工作时需要你盯着屏幕、交互输入;sed则是你说一句,它从头到尾跑一句。只要输入不是交互式终端,把vim塞进管道里会很别扭,但sed天生就是为这种批量处理设计的。
所以我的使用习惯是:凡是在脚本里要批量处理文本,优先考虑sed,而不是vim。 它不依赖终端交互、不需要打开整个文件,占用内存极小,非常适合在自动化任务中处理日志、配置文件、数据文件。
1.2 sed和vim、awk、perl的分工,很多人一开始就没搞清
初学Linux命令时最难熬的就是工具太多,不知道选谁。有个比较通俗但很有效的划分方式,我分享下个人的经验。
- vim:交互式修改文件,适合人坐在终端前,一边看一边调整,你的眼睛和手是决策者。
- sed:针对行的编辑操作,场景是“批量的、结构化的、不需要人逐步确认的”改动,比如把配置里所有8080端口改成9090、删除第20到30行、在当前匹配行之后插入一段配置。
- awk:更强的字段分析工具,适合把文本当表格处理,做统计、格式化输出、按列提取数据。比如拿到一份访问日志,要统计每个IP出现次数,我用awk比用sed顺手得多。
- perl/python:需要复杂逻辑处理文本时再上重型工具,它们能搞定任何文本问题,但为了改一行配置就启动它们,成本偏高了。
简单说,我平时写shell脚本时,sed占了文本修改的七成以上,其余才让awk或python上场。它不是那种“炫技型”命令,而是一个稳定可靠的基础工具,这也是为什么它在服务器Linux环境里基本是标配。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先把执行模型盘顺:sed为什么能边读边改
2.1 读一行、改一行、输出一行,sed的循环到底怎么转
想要真正掌握sed,第一件事不是背命令,而是理解它在后台反复执行的那个循环。这个原理几乎决定了后头所有命令表现,理解了它,你调试起来也会快得多。
sed处理输入时,大致遵循这样一个流程:
- 从输入(文件或管道)中读取一行文本,把末尾换行符去掉,放入模式空间(pattern space)。
- 对模式空间里的内容,按顺序执行脚本中给定的所有sed命令。
- 如果命令没有显式禁止输出(比如使用了-n选项),则把当前模式空间的内容打印到标准输出。
- 清空模式空间,继续读取下一行,重复以上过程。
所以对sed来说,每次处理的粒度是一行,但它的读取逻辑保证了文件不会一次性载入内存。不管一个文件是1MB还是10GB,sed在任意时刻都只保留当前正在处理的一行的内容,这种流式处理特点在Linux环境里非常宝贵。同样处理一个大日志文件,如果你写个脚本用readline逐行去读,性能通常远不如sed一条管道到底。
模式空间这个概念听起来玄乎,实际上它就是sed用来“临时放手头这一行文本”的一块工作区。绝大多数sed命令的操作对象都是模式空间的内容,你要把这一行里的foo替换成bar,本质就是在模式空间里做替换。
2.2 地址寻址:你真正需要掌握的六种写法
sed命令的通常结构是这样:
bash复制sed '地址命令'
地址用来圈定命令作用于哪些行。如果省略地址,命令会对每一行都生效。下面这六种地址写法,几乎覆盖了我日常95%的需求,建议大家优先掌握。
- 空地址:作用于所有行。比如
sed 's/foo/bar/',对所有行执行替换。 - 单行号:只作用于该行。
sed '3d'表示删除第3行。 - 行号区间:作用于某一段连续范围。
sed '2,5d'删除第2到第5行。 - 结束行号$:代表最后一行。
sed '$a\# end'表示在文件末尾追加一行。 - 正则地址:格式是
/正则表达式/,作用于所有匹配该正则的行。sed -n '/error/p'只打印包含error的行。 - 步进地址:格式是
first~step。sed -n '1~2p'表示从第1行开始,每隔2行打印一次,也就是打印奇数行。
地址还有一个重要修饰符 !,要删掉不匹配的行时很好用。sed '/^#/!d' 的含义是删除所有不以#开头的行,相当于只保留注释行。
地址还可以叠加,比如 /start/,/end/d 表示从匹配start的行开始删除,一直到匹配end的行结束。这种区间匹配在处理日志中的某段时间范围或配置文件中的server块时非常实用。
2.3 模式空间与保持空间:sed也是有状态的
不少对sed有一定了解的人,一碰到保持空间(hold space)就发怵,觉得它晦涩。其实可以把它理解为sed专门开辟的一块“草稿纸”。
模式空间每次处理新行
