sed 命令详解
更新时间:2026-08-28。本文是「一个命令一个文档」系列,聚焦
sed——文本处理三剑客之一(见文本处理命令族),与 grep 找、awk 算 并称。
sed(stream editor,流编辑器)逐行读入文本、按你给的"编辑指令"处理、输出结果。它最常被用来做替换——把配置文件里的某个值改成另一个,或者批量改写日志格式。和 grep 只"找"不同,sed 会"改"。
一、最基本的替换
sed 's/old/new/' file # 把每行第一个 old 换成 new,打印到屏幕
sed 's/old/new/g' file # g = global,一行里所有 old 都换
sed 's/old/new/2' file # 只换每行第 2 个
echo "a/b/c" | sed 's#/#-#g' # 分隔符可换,URL 里 / 多时很方便
s后面的/是分隔符,但可以换成任意字符(#、|、@都行)。当模式或替换里本身含大量/(比如路径、URL)时,换成#能少写一堆反斜杠,可读性好很多:sed 's#/old/path#/new/path#g'。
二、原地修改:-i
默认 sed 只把结果打到屏幕、不动原文件。要真改文件,用 -i:
sed -i 's/old/new/g' file # Linux:直接改
sed -i.bak 's/old/new/g' file # Linux:改之前先备份成 file.bak
sed -i '' 's/old/new/g' file # macOS/BSD:必须给备份后缀参数(空串也行)这是
sed最大的跨平台坑:macOS 的-i强制要求一个"备份后缀"参数,哪怕是空串'';而 Linux GNU sed 的-i后面直接跟脚本。写进可移植脚本时,统一写sed -i.bak最稳,改完rm *.bak即可。另外,改之前先用不带-i的命令看一眼输出,确认替换对了再原地改——这是铁律。
三、定址与范围:只对某些行动手
sed 的指令前面可以加"地址",限定作用于哪些行:
sed '1d' file # 删第 1 行
sed '$d' file # 删最后一行
sed '1,10d' file # 删 1~10 行
sed '/^#/d' file # 删所有以 # 开头的行(注释)
sed '/^$/d' file # 删空行
sed -n '10,20p' file # 只打印 10~20 行(-n 关掉默认打印)
sed '/start/,/end/p' file # 打印 start 到 end 之间的行
sed '2~2d' file # 删偶数行(从 2 开始每 2 行)
-n和p是一对:sed默认会打印每一行(处理后的),加-n关掉这个默认行为,再用p显式打印你想要的——于是sed -n '10,20p'就成了"只看第 10~20 行"的取行器,比 head/tail 组合直观。
四、反向引用:保留一部分原文
替换时想"把日期 2026-08-28 改成 08/28/2026"?用 \(...\) 捕获、\1 \2 引用:
echo "2026-08-28" | sed 's/\([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)/\2\/\3\/\1/'
# 输出 08/28/2026GNU sed 支持更省事的 \+ 和 \|(扩展正则,加 -E 或 -r):
echo "2026-08-28" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\2\/\3\/\1/'分组捕获是
sed做"重排字段"的核心。处理日志、CSV、日期格式时极常用。注意基础正则里()和{}要转义,加-E后不用——和 grep 的规则一致(详见 grep)。
五、多条指令与脚本
sed -e 's/a/b/' -e '/^#/d' file # 多条 -e
sed 's/a/b/; s/c/d/' file # 一条里用分号分隔
sed -f script.sed file # 指令写进脚本文件,复杂改写用比如统一清理配置文件:去注释、去空行、把 tab 换成空格:
sed -e '/^#/d' -e '/^$/d' -e 's/\t/ /g' config.conf六、和 grep/awk 的配合
三剑客通常是管道接力:
# 找含 error 的行,把其中 IP 脱敏,再提取时间
grep "error" app.log | sed 's/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/x.x.x.x/' | awk '{print $1, $4}'grep 先过滤出相关行,sed 改写敏感信息,awk 再抽取字段统计——这种"过滤→改写→计算"的分工是文本加工的标配。
七、实战:批量改配置
把一批 Nginx 配置里的 listen 80 改成 listen 8080,并先备份:
# 先看会改哪些(不带 -i)
grep -rn "listen 80" /etc/nginx/conf.d/
# 确认后批量替换,每个文件备份为 .bak
find /etc/nginx/conf.d -name "*.conf" -exec sed -i.bak 's/listen 80;/listen 8080;/' {} +这条命令把 find 的 -exec {} + 和 sed -i.bak 结合,是运维改配置的日常动作。改完 nginx -t 验证、回滚时直接 .bak 还原。
八、进阶:几个保命的现成写法
# 1. 改之前先"演习"——不带 -i 看会改成啥,确认再动真格
sed 's/old/new/g' file | head
# 2. 只替换第 N 次出现(如每行只改第 2 个匹配)
sed 's/foo/bar/2' file
# 3. 在匹配行前后插入内容(配置文件注入)
sed '/^server {/i # 新增上游' nginx.conf
sed '/^}/a keepalive 32;' nginx.conf
# 4. 删除某区间(含头尾)
sed '/<start>/,/<\/end>/d' xmlfile
# 5. 大小写转换(GNU sed)
sed 's/.*/\U&/' lower.txt # 全转大写第 1 条是铁律:任何 -i 原地改之前,先去掉 -i 跑一遍看 diff,尤其批量 find -exec sed -i 时,一次手滑能改错几十个文件。多文件改动养成 -i.bak 留备份习惯。
九、和文本三剑客的分工
分工顺序:grep 挑行 → sed 改写(重排/脱敏/替换)→ awk 算报表。sed 处在"改写"那一环,别拿它去做 awk 擅长的列计算。
相关命令
一句话总结
sed = 逐行流 editor,核心是 s/旧/新/旗标 替换:g 全行替换、-i 原地改(Linux 直接改、macOS 必须带后缀参数)、地址定址让指令只作用于特定行或范围、\( \) 反向引用做字段重排;配合 grep 过滤、awk 计算,构成文本加工三剑客。改文件前先看输出、必带备份,是永不翻车的两条规定。