sed 常用命令整理
sed(Stream Editor,流编辑器)是 Linux 中强大的非交互式文本处理工具。常见用途:
- 文本替换、删除、插入
- 按行/按模式筛选内容
- 配合正则表达式进行批量处理
- 与管道(
|)配合处理命令输出
目录
命令格式
sed [选项] '地址命令' [输入文件]
# 常用写法
sed 's/old/new/' file # 屏幕输出处理结果(原文件不变)
sed -i 's/old/new/g' file # 直接修改文件(GNU 写法)
command | sed 's/old/new/g' # 处理管道输入
# 注:macOS/BSD 上需写 `sed -i '' 's/old/new/g' file` 显式指定空备份后缀
常用选项
sed -n 'p' file # 静默模式(不自动打印),常配合 p 命令使用
sed -e 's/a/A/' -e 's/b/B/' file # 多点编辑(执行多条命令)
sed -f script.sed file # 从脚本文件读取 sed 命令
sed -i 's/old/new/g' file # 直接修改文件内容(in-place)
sed -i.bak 's/old/new/g' file # 先备份原文件为 .bak,再修改
sed -E 's/(abc)+/X/g' file # 使用扩展正则表达式(ERE)
sed -r 's/(abc)+/X/g' file # 同上(-E 的旧写法,GNU sed 兼容)
地址(定位要处理的行)
缺省地址表示处理所有行。可用多种方式组合定位。
# 按行号
sed '5p' file # 打印第 5 行
sed '5,10p' file # 打印 5~10 行
sed '5,$p' file # 打印第 5 行到末尾
sed '5~2p' file # 从第 5 行开始,每隔 2 行打印一次(GNU 扩展)
sed -n '1~2p' file # 打印奇数行(-n 抑制默认输出)
# 按模式(用 /pattern/ 包裹)
sed '/error/p' file # 打印包含 error 的行
sed '/error/d' file # 删除包含 error 的行
sed '/^$/d' file # 删除空行
sed '/^#/d' file # 删除以 # 开头的注释行
sed '/start/,/end/p' file # 打印从匹配 start 到匹配 end 之间的所有行
# 组合
sed '1,/error/d' file # 删除从第 1 行到第一个匹配 error 的行
sed '/start/,+5d' file # 从匹配 start 的行开始,删除其后再加 5 行(共 6 行)
核心命令
| 命令 | 说明 | 示例 |
|---|---|---|
s/regexp/replacement/[flags] |
替换 | 's/foo/bar/g' |
d |
删除行 | '/^$/d' |
p |
打印行 | -n '/error/p' |
i\text |
在匹配行之前插入文本 | '/pattern/i\新行' |
a\text |
在匹配行之后追加文本 | '/pattern/a\新行' |
c\text |
用文本替换匹配行 | '/pattern/c\新行' |
y/source/dest/ |
按字符逐个替换(类似 tr) | 'y/abc/ABC/' |
q |
处理到此处即退出 | '10q' |
r file |
读取 file 内容插入到匹配行后 | '/pattern/r file' |
w file |
将匹配行写入 file | '/error/w err.log' |
n |
读取下一行(覆盖模式空间) | 'n; p' |
N |
追加下一行到模式空间(处理多行) | 'N; s/\n/ /' |
= |
打印行号 | '/error/=' |
l |
打印行(显示不可见字符) | 'l' |
替换命令 s 的 flags
# g 全局替换(行内所有匹配,不加 g 只替换每行第一个)
sed 's/foo/bar/g' file
# n 只替换第 n 个匹配
sed 's/foo/bar/2' file # 替换每行第 2 个 foo
# p 打印发生替换的行(常与 -n 配合看哪些行被改)
sed -n 's/foo/bar/p' file
# i 忽略大小写(GNU 扩展)
sed 's/FOO/bar/gi' file
# e 将替换结果作为 shell 命令执行(GNU 扩展,注意安全风险)
# 注意:e 必须作为唯一/最后的 flag,不能与 g、p、数字等其他 flag 组合使用
sed 's/^/echo /e' file
# 多重 flags 可组合(g 与 i 可以组合)
sed -i 's/old/new/gi' file
替换中的特殊字符(转义与引用)
# / 在替换内容中需要转义
sed 's/http:\/\///g' file
# 或使用 |、#、@ 等作为分隔符,更易读
sed 's|http://||g' file
sed 's#/usr/local##' file
# & 代表「匹配到的整个内容」
sed 's/[0-9]\+/[&]/g' file # 把数字包到方括号里
# \1 ~ \9 代表正则中第 n 个捕获组
sed -E 's/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/\3\/\2\/\1/' file # 2026-06-09 → 09/06/2026
# 大小写转换(GNU 扩展,替换内容里使用)
# \L 转为小写 \U 转为大写 \E 结束转换
sed 's/^[A-Z]\+/\L&/' file
实际应用示例
# 1. 替换文件内容(最常用)
sed -i 's/old/new/g' filename # 直接修改文件
sed -i 's/old/new/g' *.txt # 批量替换多个文件
find . -name "*.conf" -exec sed -i 's/old/new/g' {} \; # 递归替换
# 2. 删除操作
sed '/^$/d' file # 删除空行
sed '/^[[:space:]]*$/d' file # 删除只包含空白字符的行
sed '/^#/d' file # 删除注释行
sed '/^$/d;/^#/d' file # 一次删除空行和注释行
sed '5d' file # 删除第 5 行
sed '5,10d' file # 删除 5~10 行
sed '$d' file # 删除最后一行
sed -n '5!p' file # 除第 5 行外都打印(注意 -n 抑制默认输出)
# 陷阱:去掉 -n 后 `sed '5!p' file` 会先自动打印一次,再用 p 多打一遍,结果是非第 5 行打 2 次、第 5 行 1 次
# 3. 插入与追加
sed '2i\这是插入的新行' file # 在第 2 行前插入
sed '2a\这是追加的新行' file # 在第 2 行后追加
sed '/pattern/i\在匹配行前插入' file
sed '/pattern/a\在匹配行后插入' file
# 4. 打印指定行
sed -n '1,5p' file # 打印 1~5 行
sed -n '5p' file # 打印第 5 行
sed -n '$p' file # 打印最后一行
sed -n '/error/p' file # 打印包含 error 的行(类似 grep)
sed -n '/start/,/end/p' file # 打印两个模式之间的内容
sed -n '1~2p' file # 打印奇数行
sed -n '2~2p' file # 打印偶数行
# 5. 多行处理
sed 'N; s/\n/ /' file # 将两行合并为一行(用空格连接)
sed 'N; s/\n//' file # 合并为一行(直接拼接)
# 6. 配合管道
ps aux | sed -n '/apache/p' # 等价于 ps aux | grep apache
cat file | sed 's/old/new/g' > newfile # 处理后输出到新文件
# dmesg | grep -i error # 忽略大小写匹配 error(grep 更直接)
# 7. 修改配置文件
sed -i 's/^#Port 22/Port 2222/' /etc/ssh/sshd_config # 取消注释并改端口
sed -i 's/^Port.*/Port 2222/' /etc/ssh/sshd_config # 直接改 Port 行
sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config # 整行替换
# 8. 在每行首/行尾添加内容
sed 's/^/prefix: /' file # 行首加前缀
sed 's/$/ suffix/' file # 行尾加后缀
sed 's/.*/ &/' file # 整行缩进 2 个空格
# 9. 提取特定列(简单场景)
# 提取 name= 后的值(BRE 写法;若同时使用 -E,要把 \( \) 改成 ( ),并把 * 转义或保留)
sed -n 's/.*name=\([^ ]*\).*/\1/p' file
# 10. 去除行首/行尾空白
sed 's/^[[:space:]]*//' file # 去除行首空白
sed 's/[[:space:]]*$//' file # 去除行尾空白
sed 与其他命令配合
# sed + grep:先过滤再处理
grep "error" log.txt | sed 's/error/ERROR/g'
# sed + awk:sed 做行级处理,awk 做字段级处理
cat file | sed '/^$/d' | awk '{print $1}'
# 多次 sed 管道(注意:-i 写在最后再处理文件更安全)
cat file | sed 's/a/A/' | sed 's/b/B/' | sed 's/c/C/'
# 用 sed 模拟 head / tail
sed '10q' file # 等价于 head -n 10 file
sed -n '6,$p' file # 等价于 tail -n +6 file(跳过前 5 行,打印第 6 行起)
# 注意:tail -n +5 与 sed -n '5,$p' 不严格等价,前者跳过前 4 行、后者包含第 5 行
文本去重技巧
场景:把一份含有重复行的列表文件处理成每条只出现一次的结果。
示例输入
假设 fruits.txt 内容如下(从用户输入或日志里导出的,可能含重复项):
apple
banana
apple
cherry
banana
date
cherry
我们希望输出:
apple
banana
cherry
date
方法 1:用 sort -u(最简单,接受打乱顺序)
sort -u fruits.txt
输出:
apple
banana
cherry
date
⚠️ 副作用:原始顺序被打乱,会按字典序重排。
方法 2:用 awk(保留原始顺序,推荐)
awk '!seen[$0]++' fruits.txt
原理:
$0代表当前整行内容seen[$0]是以行内容为 key 的关联数组- 第一次遇到某行时,
seen[$0]是空/0,取反为真 → 打印 - 自增
++把该 key 标记为 1 - 之后再次遇到同一行时,
seen[$0]是 1,取反为假 → 跳过
方法 3:纯 sed(不推荐,仅作了解)
网上流传的"纯 sed 去重"版本(如利用 hold space 做行级比对)在空行、超长行、含 / \ 这类特殊字符的行等场景下并不可靠。即使勉强能跑,写法也非常晦涩,调试和维护成本高。
这类写法可读性差、边界情况多。实际生产中请直接用方法 2(awk),可读性、稳定性和性能都更好。
方法 4:先排序去重,再恢复原顺序
awk '{print NR"\t"$0}' fruits.txt | sort -t$'\t' -k2,2 -u | sort -t$'\t' -k1,1n | cut -f2-
用行号做"暂存标签",先按内容去重,再按行号排序,最后去掉标签。
各方法对比
| 方法 | 是否保留原顺序 | 复杂度 | 适用场景 |
|---|---|---|---|
sort -u |
❌ | ⭐ | 不在意顺序的最简方案 |
awk !seen[]++ |
✅ | ⭐ | 推荐,通用、行序保持 |
纯 sed |
✅ | ⭐⭐⭐⭐ | 不推荐,仅了解思路 |
| 加行号两轮排序 | ✅ | ⭐⭐ | 需要保留顺序又只用 sort 的场景 |
注意事项与陷阱
-i会直接修改原文件,建议先用不带-i的命令测试,确认无误再添加-i。- 复杂替换务必加
-i.bak:原文件会备份为file.bak,出错可回滚。 - 正则语法:
- 默认使用 BRE(基础正则),
( ) | { }等需要转义:\(abc\)\+ - 使用
-E或-r切换为 ERE(扩展正则),更直观:sed -E 's/(abc)+/X/g'
- 默认使用 BRE(基础正则),
- 特殊字符:
/、&、\在替换内容中有特殊含义,必要时用\转义。 - macOS 与 Linux 的差异:macOS 的 BSD sed 要求
-i ''显式指定备份后缀;GNU sed 可省略。跨平台脚本建议写sed -i.bak 's/old/new/g' file。 - 大文件处理:sed 是流式处理,内存占用低,适合处理 GB 级日志。
整理日期:2026 年 6 月 9 日 · 内容以 GNU sed 4.x 行为为准,macOS/BSD 上个别 flag 和
-i用法有差异。

浙公网安备 33010602011771号