sed 是什么
sed 是面向行的流编辑器:它把输入逐行读入模式空间,对每一行依次执行脚本里的命令,默认在每行结束时打印模式空间的内容。理解这个「默认打印」是掌握 sed 的钥匙——不加 -n 时会多打印一份,所以精确输出要写成 sed -n 'p'。替换命令 s/旧/新/ 默认只替换每行的第一处,要替换全部需要 g 标志,这一点是新手最常见的偏差。
基本信息
| 适用平台 | Linux 全发行版与 macOS(GNU sed / BSD sed);-i 就地修改、-E/-r 扩展正则在两者间写法不同,脚本要留版本兼容余量 |
|---|---|
| 命令语法 | sed [选项] '脚本' [文件...];脚本由地址与命令组成,多个命令用分号或 -e 分隔 |
| 常用选项 | -n 静默(不自动打印)、-e 指定脚本片段、-i 就地修改文件、-E 使用扩展正则、-f 从文件读脚本、-s 把多个文件当独立流处理 |
| 常用命令 | s 替换、d 删除行、p 打印行、a/i 追加/插入、c 整行替换、y 字符转换、q 提前退出、n 读入下一行 |
| 地址写法 | 行号(3、2,5)、$ 最后一行、/正则/、/起点/,/终点/、1~2 表示奇数行 |
典型使用场景
- 批量改配置:替换端口、路径、主机名,配合 -i.bak 保留原文件退路
- 按范围取行:sed -n '1,20p' 或按起止正则截取某段日志两次发布时间之间的内容
- 删除匹配行:清理空行、注释行与调试输出,例如 sed '/^#/d'
- 在指定位置插入或追加内容:在某行之后加入配置项,a 与 i 完成插入追加
- 字符级转换:y 命令做大小写或字符映射,比正则替换更直接
- 流式处理管道数据:从标准输入读入,不需要中间文件,适合与 grep、awk 串联
常用示例
常用示例
sed 's/http/https/' config.txt # 只换每行第一处
sed 's/http/https/g' config.txt # 全局替换
sed -n '1,20p' app.log # 只看 1 到 20 行
sed -n '/ERROR/p' app.log # 只打印含 ERROR 的行
sed '/^$/d;/^#/d' conf.ini # 删空行与注释行
sed -e 's/a/b/' -e 's/c/d/' f # 多段脚本
sed -i.bak 's/8080/8081/g' app.conf # 就地修改并留备份
sed -n '/BEGIN/,/END/p' data.txt # 截取两个标记之间的内容常用命令对照
| 写法 | 作用 | 注意 |
|---|---|---|
| s/旧/新/g | 替换,g 表示每行全部替换 | 不加 g 只换第一处 |
| s/旧/新/I | 忽略大小写替换 | GNU 扩展,BSD 写法不同 |
| d | 删除匹配的行 | 常与前缀地址组合,如 /^#/d |
| p | 打印当前模式空间 | 必须配 -n,否则内容会重复输出一次 |
| a\ 内容 | 在匹配行之后追加一行 | GNU 允许 a 内容 的简写形式 |
| c\ 内容 | 用新内容替换整行 | 只作用于被匹配的行本身 |
分隔符不限于斜杠:路径里全是斜杠时换成 sed 's#/opt/app#/srv/app#g' 更易读。替换内容里需要字面量的 & 与反斜杠时要转义——& 在替换串里表示整个匹配内容,误用会让结果多出一段原文。
sed 按行处理,模式空间里一次只放一行,跨行匹配需要 N 或 -z 之类的技巧,难度陡增。处理多行结构、字段计算或复杂条件时应考虑 awk 或 perl,可读性与正确性都更好。
sed -i 直接改写原文件,出错就没有回退。生产环境统一写 sed -i.bak 保留备份,改完用 diff 对比确认差异范围,再决定是否保留备份文件。
工具选择的边界:纯文本的行级替换与截取用 sed 最轻便;涉及字段、条件与聚合时换 awk;改动 JSON、YAML、XML 这类结构化文件时,用 jq、yq 之类理解语法的工具去做,正则替换在这些格式上很容易因为缩进、引号或嵌套结构产生难以察觉的错误。