sed (流编辑器 / Stream Editor)

1. 定义

sed 是 Unix 下逐行处理文本流的非交互式编辑器,按脚本指令对输入做查找、替换、删除、插入等操作,常用于批量改文本、清洗日志、管道中间加工。

类比:grep 负责”找到行”,sed 负责”顺手改掉它”——像一条流水线上的自动修改工位。

2. sed 能做什么

场景作用
批量替换把一个词全局替换成另一个(如改配置、重命名)
删除行删空行、删注释、删匹配某模式的行
提取/加工配合正则改写每一行内容
管道加工在命令链中间实时改写文本流

3. 核心概念

  • 脚本 (script):传给 sed 的编辑指令,形如 's/旧/新/''/模式/d'
  • 地址 (address):指定”对哪些行”生效,可以是行号、行范围或正则匹配
  • -i 原地编辑:直接修改文件(不加则只输出到终端,不改原文件)
  • -E 扩展正则:支持 + () {} 等,少转义
  • & 与捕获组 \1:替换时引用匹配到的内容

4. 常用命令

替换(最常用)

sed 's/foo/bar/' file.txt              # 每行第一个 foo 改成 bar(输出到终端)
sed 's/foo/bar/g' file.txt             # g = 全局,每行所有 foo 都改
sed 's/foo/bar/gi' file.txt            # i = 忽略大小写
sed -E 's/([0-9]+)/#\1/' file.txt      # \1 引用捕获组,给数字加 # 前缀
sed 's/.*@//' emails.txt               # 删掉 @ 之前的内容,只留域名

原地修改文件

sed -i 's/old/new/g' config.txt        # 直接改文件(GNU sed)
sed -i '' 's/old/new/g' config.txt     # macOS/BSD sed 需要空字符串参数
sed -i.bak 's/old/new/g' config.txt    # 改前自动备份为 config.txt.bak

删除与打印

sed '/^$/d' file.txt                   # 删空行
sed '/#/d' file.txt                    # 删含 # 的行(注释)
sed '1,5d' file.txt                    # 删第 1~5 行
sed -n '10,20p' file.txt              # -n 关闭默认打印,只打印 10~20 行
sed -n '/ERROR/p' app.log             # 只打印含 ERROR 的行(类似 grep)

插入 / 追加 / 行号

sed '1i\#!/bin/bash' script.sh         # 在第 1 行前插入
sed '$a\EOF' file.txt                  # 在最后一行后追加
sed '=' file.txt                       # 每行前加行号

管道组合

cat access.log | sed 's/ - / | /g' | grep 500     # 先改写再过滤
ps aux | sed -n '1p;3,5p'                         # 打印第 1、3~5 行

5. sed vs 其他文本工具

工具擅长何时用
sed行级查找替换、删除流式批量改文本、管道加工
grep只匹配不修改单纯找行、过滤
awk按列处理、计算、格式化需要按字段切分、统计
tr字符级替换/删除简单单字符映射(如大小写、空格换制表符)
perl -pie更强大的正则(PCRE)需要 look-around 等高级正则时

6. 典型工作流

批量改配置

sed -i 's/localhost:8080/prod.example.com/g' *.conf   # 全项目替换地址

清洗日志

sed '/^$/d;/DEBUG/d' app.log > clean.log   # 去空行 + 去 DEBUG 行

提取关键字段

sed -E 's/.*user=([a-z]+).*/\1/' access.log   # 抽出每行 user= 后面的值

7. 常见误区

  • ❌ “sed 改了文件却没变化”。忘了加 -i——默认只把结果打印到终端,不动原文件。
  • ❌ “在 macOS 上 -i 报语法错”。BSD sed 的 -i 必须带备份后缀参数(哪怕空串 ''),和 GNU sed 不同。
  • ❌ “替换斜杠 / 时要疯狂转义”。分隔符可换成别的字符避免转义,如 sed 's#http://#https://#g'
  • ❌ “想替换多行内容”。sed 默认按行处理,跨行替换要用 N 或换 perl/awk

8. 延伸阅读 / 关联概念

  • grep — 只找不改,和 sed 常串联
  • awk — 按列加工与统计,处理更复杂的结构化文本
  • tr — 字符级简单替换
  • 正则表达式(BRE / ERE)——sed 匹配与替换的核心
  • GNU sed 文档:https://www.gnu.org/software/sed/manual/