sed替换命令基本格式为s/原字符串/新字符串/选项,常见错误包括漏分隔符、未转义元字符、误用全局标志;跨平台使用-i需注意GNU与BSD差异;复杂场景建议改用awk。

sed 替换命令的基本写法和常见错误
sed 的替换操作核心是 s///,不是 replace 或 substitute 这类关键词。漏写分隔符、忘记转义特殊字符、误用全局标志,是初学者最常触发「没生效」或「报错」的三类问题。
- 基础格式必须是
sed 's/原字符串/新字符串/选项',斜杠是默认分隔符,但可换成其他字符(如s|/old|/new|g)来避免路径中斜杠冲突 - 原字符串含
.、*、^、$等正则元字符时,必须用反斜杠转义,例如匹配字面量file.txt要写成file.txt - 不加
g标志只替换每行第一个匹配项;加了才全局替换;加i才忽略大小写(如s/ERROR/error/gi) - 直接运行
sed 's/foo/bar/' file.txt不会修改原文件,只是输出结果到 stdout —— 想保存得用重定向或-i选项
就地修改文件时 -i 选项的兼容性陷阱
sed -i 在不同系统行为不一致:GNU sed(Linux)允许空后缀,BSD sed(macOS)强制要求后缀参数。直接写 sed -i 's/.../.../' file 在 macOS 上会报错 command i expects followed by text。
- Linux 安全写法:
sed -i.bak 's/old/new/g' file.txt(备份原文件为file.txt.bak,再修改) - macOS 必须显式提供后缀:
sed -i '.bak' 's/old/new/g' file.txt;若不想留备份,用sed -i '' 's/old/new/g' file.txt(注意空字符串要用引号包裹) - 跨平台脚本中,建议统一用临时文件 + mv 方式替代
-i,避免环境差异导致失败
匹配整行、单词边界与多行替换的典型场景
单纯靠 s/xxx/yyy/ 很难精准控制上下文,比如只想替换独立单词 cat,而不碰 scatter;或想把跨两行的段落替换成单行内容。
- 匹配完整单词:用
(GNU sed)或[[:<:>/<code>[[:>:]](BSD),例如sed 's/cat/kitten/g' - 匹配整行内容:用
^和$锚定,例如sed '/^#.*$/d'删除所有以 # 开头的整行注释 - 多行处理需用
N命令读入下一行,再用s匹配换行符,例如sed ':a;N;$!ba;s/first second/merged/' file(先累积全部内容,再替换) - 注意:多行模式下
^和$含义会变,不再指“行首/行尾”,而是“缓冲区开头/结尾”
替换内容含变量或特殊字符的处理方式
shell 变量不能直接放进单引号里,而双引号又会让 $、 等被 shell 提前解析,容易导致正则失效或命令注入。
- 变量内含斜杠时,改用其他分隔符:假设
OLD="/path/to",用sed "s|$OLD|/new/path|g"比硬转义更清晰 - 变量含正则元字符(如
VER="1.2.3"),需先用脚本预处理转义点号:ESCAPED=$(printf '%s' "$VER" | sed 's/./\./g'),再拼进命令 - 避免用
eval拼接 sed 命令 —— 输入不可控时有严重安全风险;优先考虑用awk或临时文件中转 - 替换内容含换行符?sed 本身不支持直接插入
到替换字段(除 GNU sed 的扩展外),此时应切换到awk或perl
真正麻烦的不是语法记不住,而是 sed 对“行”的抽象太强,一旦跳出单行、无状态、非贪婪的舒适区,就得反复验证缓冲区状态和地址范围。实际工程中,超过三步的 sed 脚本建议直接上 awk。

















