介绍
sed(stream editor)流编辑器,按行读取文本、处理后输出,默认不修改原文件,只输出到标准输出。 核心:sed [选项] '脚本' 文件名
应用场景
非交互式、按行处理文本,适合脚本自动化
- 配置文件自动化维护:批量替换 IP / 域名 / 端口、增删注释、插入 / 删除配置行(部署脚本高频)
- 日志清洗:过滤指定日志行、截取时间段日志、清理多余空白,大文件流式读取省内存
- 批量多文件文本替换:项目内批量修改代码、文档内容,搭配 find 批量处理
- 管道数据预处理:对命令输出做提取、裁剪,作为 grep/awk 的前置文本加工
- 文本格式修正:换行符转换、去除首尾空格、字符映射转换
一、常用选项
| 参数 | 说明 |
|---|---|
-n |
只输出匹配到的行,不打印所有行(常用) |
-e |
追加多个编辑命令,多个表达式 |
-f file |
从文件读取sed脚本 |
-i |
直接修改原文件(高危!建议先用 -i.bak 备份) |
-r / -E |
使用扩展正则表达式(不用转义 `()+? |
⚠️
-i.bak:修改原文件,同时生成xxx.bak备份文件,生产环境强烈推荐。
二、sed 脚本语法
格式:[地址]命令[参数]
- 地址:限定哪些行执行命令;没有地址=所有行
- 数字:
3第3行;3,53~5行 /正则/:匹配正则的行$:最后一行3,$:第3行到末尾
- 数字:
- 命令:增删改查
基础命令速查表
| 命令 | 全称 | 作用 |
|---|---|---|
p |
打印行,配合 -n |
|
d |
delete | 删除行 |
s |
substitute | 替换(最常用) |
a |
append | 行后追加文本 |
i |
insert | 行前插入文本 |
c |
change | 替换整行 |
y |
translate | 字符一对一转换 |
q |
quit | 匹配后退出sed |
三、基本使用
准备文件
执行下面命令,创建测试文本文件:test.txt
cat > test.txt <<EOF
apple 100
banana 200
orange 300
apple 400
EOF
1. 打印(p),搭配 -n
# 打印第2行
sed -n '2p' test.txt
# 打印2~3行
sed -n '2,3p' test.txt
# 打印最后一行
sed -n '$p' test.txt
# 匹配包含apple的行
sed -n '/apple/p' test.txt
# 从第2行开始,直到匹配orange停止
sed -n '2,/orange/p' test.txt
2. 删除行 d
只是输出删除,原文件不变,加-i才改文件
# 删除第1行
sed '1d' test.txt
# 删除1~2行
sed '1,2d' test.txt
# 删除最后一行
sed '$d' test.txt
# 删除包含banana的行
sed '/banana/d' test.txt
# 删除空行
sed '/^$/d' test.txt
3. 替换 s/// (重要)
语法:s/查找内容/替换内容/标记
标记:
g:global 全局替换(一行内所有匹配,不加g只替换第一个)i:忽略大小写p:打印匹配行(配合-n)w file:把匹配行写入文件
# 把apple换成pear,每行只替换第一个
sed 's/apple/pear/' test.txt
# 全局替换所有apple
sed 's/apple/pear/g' test.txt
# 忽略大小写替换
sed 's/apple/pear/gi' test.txt
# 使用#作为分隔符(路径替换时好用,避免/转义)
sed 's#/usr/bin#/usr/local/bin#g'
# 只输出替换成功的行
sed -n 's/apple/pear/gp' test.txt
分组捕获(扩展正则
-E)\1代表第一个括号匹配内容
# 提取单词,分组
echo "abc123def" | sed -E 's/([a-z]+)([0-9]+)([a-z]+)/\1_\2_\3/'
# 输出 abc_123_def
4. 插入、追加、整行替换 i a c
# i:第2行前面插入一行 hello
sed '2i hello' test.txt
# a:第2行后面插入一行 hello
sed '2a hello' test.txt
# c:把第2行整行替换成 hello
sed '2c hello' test.txt
# 在匹配apple的行后面追加
sed '/apple/a add_line' test.txt
5. 字符转换 y
一对一字符映射,不是正则!
# a→A,b→B,1→!
echo "a1b" | sed 'y/ab1/AB!/'
# A!B
6. 多命令执行
方式1:-e
sed -e 's/apple/APPLE/g' -e '/banana/d' test.txt
方式2:分号 ;
sed 's/apple/APPLE/g;/banana/d' test.txt
7. 修改原文件 -i
# 推荐:修改,并且备份 test.txt.bak
sed -i.bak 's/apple/pear/g' test.txt
# 不备份,直接修改(GNU sed,MacOS不推荐)
sed -i 's/apple/pear/g' test.txt
MacOS 注意:
sed -i '' 'xxx' file,必须加空引号。
8. 退出 q
找到匹配行就停止读取文件,提升大文件性能
sed '/orange/q' test.txt
四、正则在sed里的使用
sed 默认基础正则:^ $ . * [],() {} + ? | 需要转义 \( \) \{ \}加 -E(GNU sed)启用扩展正则,不用转义:
^行开头$行结尾.任意单个字符*前面字符0次或多次+1次以上(-E)?0或1次(-E)|或(-E)()分组(-E)
示例:
# 删除以#开头的注释行
sed '/^#/d' test.txt
# 删除空格+#开头注释行
sed -E '/^[[:space:]]*#/d' test.txt
# 去掉行尾空白
sed -E 's/[[:space:]]+$//' test.txt
[[:space:]]匹配空格、tab,POSIX标准,比\s兼容性更好。
五、实用高频脚本
# 1. 删除注释行和空行
sed -E '/^[[:space:]]*#/d; /^$/d' nginx.conf
# 2. 批量替换文件内容(带备份)
sed -i.bak 's/old_str/new_str/g' *.conf
# 3. 在文件第一行插入文字
sed -i '1i # new header' test.txt
# 4. 在文件末尾追加文字
sed -i '$a # end line' test.txt
# 5. 提取ip(示例)
echo "192.168.1.100 server" | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/'
# 6. 去掉每行开头空格
sed -E 's/^[[:space:]]+//' test.txt
六、sed 工作原理
- 读取一行到模式空间(pattern space)
- 执行sed脚本命令处理模式空间内容
- 默认打印模式空间,清空,继续读下一行
保持空间(hold space)高级用法:
h H g G x,用于多行处理。
高级:保持空间简单示例(多行处理)
# h:模式空间复制到保持空间;G:保持空间追加到模式空间
sed '/apple/h;${x;p}' test.txt
七、坑点总结
- sed 默认不修改原文件,必须
-i;优先-i.bak - 不加
g,替换只替换一行中第一个匹配 /作为分隔符,替换路径建议改用s#xxx#yyy#- MacOS sed 是BSD sed,和GNU sed有差异(-i参数、正则)
- 地址范围
start,end:start匹配后开始,end匹配后结束,后续重新寻找start