主题
sed 命令详解:流式批量编辑文本
本文是 Linux 命令速查 中
sed的从 0 到 1 详解。 目标:把sed --help里的选项和s///、p、d、地址定址、分组讲清楚,多看几遍后,你在服务器上敲sed --help就知道该用哪个。 环境依据:GNU sed 4.8(Ubuntu 22.04 自带;RHEL/Rocky 自带版本用法一致)。
一、命令是干什么的
sed 是 stream editor(流式编辑器):它一行行读输入,按你给的"脚本"对每行做处理(替换、删除、打印),再输出。最常见的用途是批量替换文件里的字符串,不用打开编辑器手动改。
- 替换:
sed 's/旧词/新词/g'; - 删行:
sed '/某词/d'; - 打印指定行:
sed -n '10,20p'; - 加
-i直接改原文件。
类比:
sed就像一个"自动批改机",把文件每一行递进去,它按规则改完再吐出来。你不用打开 vim 一行行找替换,一条命令把几百个文件里的old.com全改成new.com。它是文本三剑客之一。
它属 sed 包。
二、命令语法
bash
sed [选项] '脚本命令' [文件]...[选项]:如-n(静默)、-i(原地改)、-E(扩展正则)、-e(指定脚本);'脚本命令':sed 的核心,形如地址+s/旧/新/;[文件]:要处理谁;不写就从标准输入读。
sed 默认把每行都输出,加 -n 后只有主动 p 的行才输出。
三、选项全表(对照 sed --help)
1. 命令行选项
| 选项 | 中文含义 | 什么场景用 |
|---|---|---|
-n,--quiet,--silent | 静默:不自动打印每行,只打印脚本里 p 的行 | 只想看指定行时(常用) |
-e 脚本,--expression=脚本 | 指定一段脚本(可多次用,串多个动作) | 一条命令里做好几件事 |
-f 脚本文件 | 从文件读脚本 | 脚本很长时 |
-i[后缀],--in-place[=后缀] | 直接改原文件;给后缀则生成备份(如 -i.bak) | 批量改文件(高危) |
-E,-r | 用扩展正则(支持 +、()、|) | 写分组捕获时(推荐) |
-z | 按 NUL 而不是换行分隔 | 处理特殊文件名 |
--posix | 关掉 GNU 扩展 | 追求可移植时 |
2. sed 脚本里的常用命令(核心)
| 命令 | 作用 | 示例 |
|---|---|---|
s/旧/新/ | 替换每行第一个匹配 | s/foo/bar/ |
s/旧/新/g | 替换全行所有匹配 | s/a/X/g |
p | 打印当前行 | 配合 -n 选行 |
d | 删除当前行 | d |
地址 | 只对匹配的行生效 | 10,20(第10-20行)、/关键词/ |
& | 代表"整个匹配到的串" | s/[0-9]*/[&]/ 给数字加括号 |
\1 \2 | 分组捕获的第 1、2 段 | 配合 -E 的 () |
地址定址是 sed 的精髓:可以给行号(
5、1,10、$最后一行),也可以给正则(/error/),写在命令前面就表示"只对这些行动手"。
四、由浅入深的典型示例
演示在 /tmp/sre_shard_txt 下。
示例 1:基本替换
bash
echo "hello world 123" | sed 's/world/SED/'text
hello SED 123
s/旧/新/把第一个world换成SED。
示例 2:全局替换(加 g)
bash
echo "a b a c a" | sed 's/a/X/g'text
X b X c X不加
g只换第一个;加g(global)一行里所有a都换掉。
示例 3:不加 g 只换第一个
bash
echo "a b a c a" | sed 's/a/X/'text
X b a c a只有开头第一个
a被换,后面的不动。
示例 4:静默模式打印指定行(-n + p)
bash
sed -n '2,4p' demo.txttext
banana
apple
cherry
-n关掉默认全打印,2,4p只打印第 2 到 4 行。这等于head/tail的灵活版,能取任意行段。
示例 5:只打印含某词的行
bash
sed -n '/apple/p' demo.txttext
apple
apple
apple地址
/apple/表示"只对含 apple 的行",再p打印——效果类似grep apple。
示例 6:删除含某词的行(d)
bash
sed '/apple/d' demo.txttext
banana
cherry
banana
date
/apple/d:含 apple 的行直接删掉,剩下的照常输出。
示例 7:按行号删除
bash
sed '3d' demo.txttext
apple
banana
cherry
banana
apple
date删掉第 3 行(原来是
apple)。也可以sed '3,5d'删一段。
示例 8:用 & 引用整个匹配
bash
echo "version 123" | sed 's/[0-9][0-9]*/[&]/'text
version [123]
&代表"正则匹配到的那一段",这里把数字123包进方括号。
示例 9:分组捕获(-E + \1\2)
bash
echo "phone 13812345678" | sed -E 's/([0-9]{3})([0-9]{4})([0-9]{4})/\1-\2-\3/'text
phone 138-1234-5678
-E开启扩展正则,()分三组,\1 \2 \3分别引用,于是手机号被切成138-1234-5678。
示例 10:原地改文件并备份(-i)
bash
cp demo.txt demo.bak.txt
sed -i.bak 's/apple/APPLE/g' demo.bak.txt
cat demo.bak.txttext
APPLE
banana
APPLE
cherry
banana
APPLE
date
-i.bak直接改demo.bak.txt,同时把原文件备份成demo.bak.txt.bak。生产批量改前一定先不加-i跑一遍看效果,确认无误再加。
示例 11:多个动作串起来(-e)
bash
echo "Hello World" | sed -e 's/Hello/Hi/' -e 's/World/There/'text
Hi There两个
-e依次执行:先把 Hello 换成 Hi,再把 World 换成 There。
示例 12:只在匹配行上替换
bash
grep ERROR app.log | sed 's/ERROR/!!! ERROR !!!/'text
2026-09-30 10:00:04 !!! ERROR !!! db connection failed
2026-09-30 10:00:07 !!! ERROR !!! timeout先 grep 出错误行,再用 sed 给 ERROR 加高亮标记——三剑客常这么接力。
五、高频组合速记
| 命令 | 用途 |
|---|---|
sed 's/旧/新/g' 文件 | 全局替换(输出到屏幕) |
sed -i 's/旧/新/g' 文件 | 直接改原文件 |
sed -i.bak 's/旧/新/g' 文件 | 改原文件 + 备份(推荐) |
sed -n '10,20p' 文件 | 只看第 10-20 行 |
sed '/词/d' 文件 | 删除含某词的行 |
sed 's/^/前缀 /' | 每行开头加内容 |
sed 's/$/后缀/' | 每行结尾加内容 |
sed -E 's/(..)/(..)/\2\1/' | 分组重排 |
六、RHEL 系与 Debian 系差异
sed 属 GNU sed,两系基本一致。一个重要差异:
-i备份写法:GNU sed(两系都是)用-i.bak(中间无空格);BSD/macOS 的 sed 用-i ''。在 Linux 上一律用-i.bak或-i。-E两系都支持。
七、新手易错点
-i直接改原文件:不加-i只改显示不存盘;加了就真改。批量操作前先预览。s/.../.../末尾别漏斜杠:少一个/就报语法错。- 不加
g只换每行第一个:想全换记得g。 sed 's/a/b'不会停:它流式处理所有行,不是只处理一行。&和\1只在替换部分有意义:它们引用匹配结果,不能随便乱用。- 危险提示:
sed -i批量改文件不可逆,先备份、先预览;-i后面别乱加空格。
八、相关命令与文档
- 速查页:Linux 命令速查
- 找行:
grep(详解见 grep) - 按列处理:
awk(详解见 awk) - 管道原理:见 重定向与管道