定义:Stream Editor(流编辑器)。
机制:sed 维护一个“模式空间 (Pattern Space)”。它按行读取文件,将当前行放入空间,执行命令,输出结果,然后清空空间读取下一行。
1sed [选项] '定位 + 动作' 文件名
| 选项 | 英文全称 | 解释 | 典型场景 |
|---|---|---|---|
-i | --in-place | 直接修改原文件。默认 sed 只是输出到屏幕。 | 修改配置文件 |
-n | --quiet | 静默模式。关闭默认输出,通常配合 p 动作使用。 | 提取特定行 |
-E | --regexp-extended | 启用扩展正则。使用 +, ?, ` | ,()` 时无需转义。 |
-e | --expression | 多点编辑。允许在一个命令中执行多个脚本。 | 一次做多件事 |
⚠️ 安全警告 (macOS vs Linux):
- Linux:
sed -i 's/a/b/' file- macOS: 强制要求备份后缀。若不备份必须传空:
sed -i '' 's/a/b/' file- 通用安全写法:
sed -i.bak 's/a/b/' file(修改前自动创建 file.bak)
sed 的强大之处在于精准定位。
41sed '10d' file.txt # 操作第 10 行2sed '5,10d' file.txt # 操作第 5 到第 10 行3sed '10,$d' file.txt # 操作第 10 行到最后一行 ($ 代表末尾)4sed '1~2d' file.txt # 步进操作:从第1行开始,每隔2行操作一次 (即删除奇数行 1,3,5...)
21sed '/Error/d' file.txt # 操作包含 "Error" 的行2sed '/^#/d' file.txt # 操作以 # 开头的行
语法:'/开始标记/,/结束标记/ 动作'
21# 打印从 "Start" 出现到 "End" 出现之间的所有行2sed -n '/Start/,/End/p' file.log
s
语法:s/正则/新内容/标记
81# 只替换每行第一个匹配项2sed 's/apple/banana/' file.txt34# 全局替换 (g = global)5sed 's/apple/banana/g' file.txt67# 忽略大小写替换 (I = Ignore case)8sed 's/apple/banana/I' file.txt
当你要替换路径(包含 /)时,使用 / 作为分隔符会非常痛苦(需要疯狂转义 \/)。
技巧: sed 允许你用任何字符作为分隔符,常用 #, @, |。
51# 痛苦写法2sed 's/\/usr\/local\/bin/\/bin/g' file.txt34# 优雅写法5sed 's#/usr/local/bin#/bin#g' file.txt
这是 sed 最核心的高级功能。使用 () 捕获内容,用 \1, \2 引用它。
强烈建议配合 -E 使用。
案例 A:调整词序
将 "Hello World" 换成 "World Hello"
11echo "Hello World" | sed -E 's/(\w+) (\w+)/\2 \1/'案例 B:保留部分,修改部分
比如:image: nginx:1.19 -> image: nginx:latest,但你只知道它以 image: nginx: 开头。
21# \1 代表第一个括号匹配到的内容 (image: nginx:)2sed -E 's/(image: nginx:).*/\1latest/' docker-compose.yml
& 符号& 代表“匹配到的整个查找串”。
案例:给所有 "Failed" 单词加上中括号
21# 输出 [Failed]2echo "Status: Failed" | sed 's/Failed/[&]/'
| 动作 | 含义 | 示例 |
|---|---|---|
d | Delete (删除) | sed '/DEBUG/d' config (删包含 DEBUG 的行) |
p | Print (打印) | sed -n '/Error/p' log (只打包含 Error 的行) |
a | Append (行后追加) | sed '1a Hello' file (在第1行下面加一行) |
i | Insert (行前插入) | sed '/root/i #User' file (在匹配行上面加一行) |
c | Change (整行替换) | sed '/SELINUX=/c SELINUX=disabled' config |
多行追加技巧:
在追加的内容中使用 \n 换行。
11sed '1a 第一行追加\n第二行追加' file.txt
目标:把 nginx.conf 中的 worker_processes 1; 改为 worker_processes auto;
21# ^ 锚定行首,确保不会误改注释,\s+ 匹配任意空格2sed -E -i 's/^(worker_processes)\s+[0-9]+;/\1 auto;/' nginx.conf
这是清理配置文件的标准操作。
41# -e 允许同时执行两个操作2# 1. /^\s*#/d 删除以 # 开头的行 (包括前面有空格的)3# 2. /^\s*$/d 删除空行 (包括只有空格的行)4sed -i -e '/^\s*#/d' -e '/^\s*$/d' config.conf
从 ip addr 命令中提取 IP。
41ip addr show eth0 | grep 'inet ' | sed -E 's/.*inet (.*)\/24.*/\1/'2# 逻辑:3# 1. grep 筛选出包含 inet 的行4# 2. sed 替换:把 "inet 之前的一堆" 和 "/24 之后的一堆" 都删掉,只保留括号里的 IP
虽然 cat -n 可以做,但用 sed 也可以。
51sed '=' file.txt | sed 'N;s/\n/ /'2# 解释:3# = 打印行号 (行号会独占一行)4# N 把下一行读上来拼接到当前行5# s/\n/ / 把中间的换行符换成空格
这是新手最容易犯错的地方。
'...':Shell 不会解析变量,$VAR 只是普通字符。"...":Shell 会解析变量。
81old_port="80"2new_port="8080"34# ❌ 错误:sed 会试图寻找字面量 $old_port5sed 's/$old_port/$new_port/g' config67# ✅ 正确:使用双引号8sed "s/$old_port/$new_port/g" config
正则默认是贪婪的(尽可能多匹配)。
文本:粗体普通又粗体
命令:sed 's/.*<\/b>//g'
结果: (全被删了,因为 .* 直接匹配到了最后一个 )
解决: sed 不支持非贪婪修饰符 .*? (Perl/Python 支持)。在 sed 中需要变通:
21sed 's/<b>[^<]*<\/b>//g'2# [^<]* 意为:匹配非 < 的任意字符,遇到下一个 < 就停止