默认 sed 's/old/new/g' 是字符串匹配而非单词匹配,故会替换子串(如 cat 在 category 中也被替换);要精确匹配完整单词,须使用单词边界锚点 \b(gnu sed)或 \(传统 sed),例如 sed -i 's/\bcat\b/new/g' file.txt。

sed 替换单词时为什么只替换了部分匹配?
默认 sed 's/old/new/g' 是按字符串匹配,不是按“单词”边界。比如替换 cat,会把 category 里的 cat 也干掉。
要真正只替换完整单词,必须用单词边界锚点:\b(GNU sed)或 \ / <code>\>(传统 sed)。
-
sed -i 's/\bcat\b/new/g' file.txt—— 推荐,兼容多数现代 Linux 发行版 -
sed -i 's/\<cat>/new/g' file.txt</cat>—— 在 macOS 或老版本 sed 中更稳妥 - 避免写成
s/cat/new/g,否则scat、concat全中招
vim 里怎么安全地全词替换并确认?
在 vim 打开文件后,直接输命令容易手滑。先开高亮再操作更可控:
-
:set hlsearch—— 开启搜索高亮,输入/\<word></word>看是否只框住独立单词 -
:%s/\<word>/replacement/gc</word>——c表示每处都停住问你,g保证一行多处也处理 - 如果只想换当前缓冲区(非全部打开的文件),别用
:argdo,直接:%s就够 - 误操作后按
u撤销,别急着:q!—— vim 的撤销粒度很细
批量处理多个文件时,sed -i 怎么避免覆盖出错?
-i 直接改文件风险高,尤其跨目录或通配符匹配时。真实场景下容易踩的坑:
- 没加备份后缀:
sed -i 's/foo/bar/g' *.txt→ 所有文件瞬间不可逆修改 - 路径含空格或特殊字符:
sed -i ... $(find . -name "*.log")会崩,改用find ... -exec sed -i.bak ... {} + - 想跳过二进制文件却没过滤:加
file -b {} | grep -q text判断再处理 - 真正保险的做法:
sed 's/foo/bar/g' file.txt > tmp && mv tmp file.txt,不依赖-i
grep 预筛选 + sed 执行,为什么比单条 sed 更可靠?
直接上 sed -i 像闭眼扫雷。先确认目标存在、位置合理,再动手:
- 查哪些文件含该词:
grep -l '\<word>' *.md</word>,列出候选文件 - 看上下文是否安全:
grep -n -A1 -B1 '\<word>' target.md</word>,检查前后行有没有敏感结构(如代码块、注释) - 预览替换效果:
sed 's/\bword\b/repl/g' target.md | head -20,确认格式没崩 - 最后才加
-i;如果涉及正则中的/、.、*,换分隔符更稳,比如sed 's|/old/path|/new/path|g'
单词边界和备份习惯是两条硬线,漏掉一个就可能丢数据。别信“就改一个词没事”,Linux 下没有“就一个”。











