Linux sed批量替换文本:从单文件到多目录的实操方法
在 Linux 里批量替换文本,最常用的组合是 sed 配合 find 或 grep。sed 负责按行做替换,find 负责把需要处理的文件找出来。
本文按零基础能直接照做的顺序,讲清单文件替换、多文件批量替换、递归目录替换,以及替换前必须做的备份和替换后的验证。
先确认替换目标和文件范围
动手前先明确两件事:要替换的旧内容是什么,要处理哪些文件。
建议先用 grep 确认旧内容出现的位置,避免误改配置。
# 查看当前目录下哪些文件包含旧字符串
grep -rl "old_text" .
-r 表示递归子目录,-l 表示只列文件名不打印匹配行。
如果输出为空,说明当前路径下没有匹配内容,需要换目录或检查拼写。
替换前务必先备份。
对重要配置文件,可以复制一份带日期的备份:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
对于目录批量操作,建议先打包备份整个目录,确认无误后再删除备份。
单文件替换:先跑通再扩大范围
sed 替换的基本语法是 sed 's/旧内容/新内容/' 文件。
默认只替换每行第一处匹配,加上 g 才会替换一行中的所有匹配。
sed -i 's/old_text/new_text/g' demo.conf
参数说明:
-i:直接修改原文件,不加这个参数只输出到屏幕,不写回文件。s:substitute,表示替换操作。g:global,表示一行内全部替换。
如果只想先看效果,不修改文件,可以先去掉 -i:
sed 's/old_text/new_text/g' demo.conf
确认输出正确后,再补上 -i 执行。
使用 GNU sed 时,可以用 -i.bak 在修改前自动生成备份:
sed -i.bak 's/old_text/new_text/g' demo.conf
这样会生成 demo.conf.bak,原文件被修改。
如果系统是 macOS 或 BSD 系,-i 后面必须跟一个参数,常见写法是 sed -i '' 's/old/new/g' file,否则会报错。
多文件与递归目录批量替换
当文件分散在多个目录时,用 find 把文件找出来,再交给 sed 处理。
下面的命令会替换当前目录及子目录下所有 .conf 文件中的内容:
find . -type f -name "*.conf" -exec sed -i 's/old_text/new_text/g' {} +
{} 代表 find 找到的每个文件,+ 表示尽量把多个文件一次传给 sed,效率比每个文件单独调用一次高。
如果只想处理包含旧字符串的文件,可以减少无效写入:
find . -type f -name "*.conf" -exec grep -l "old_text" {} + | xargs sed -i 's/old_text/new_text/g'
处理文件名包含空格的情况,建议用 -print0 和 xargs -0:
find . -type f -name "*.conf" -print0 | xargs -0 sed -i 's/old_text/new_text/g'
如果文件很多,可以先在测试目录跑一遍,确认命令和结果都正确,再对生产目录执行。
特殊字符、路径和变量替换的避坑点
sed 默认用 / 作为分隔符,如果替换内容本身包含 /,比如路径,直接写会报错。
可以换一个不冲突的分隔符:
sed -i 's#/var/www/html#/data/www#g' site.conf
这里用 # 代替 /,读起来也更清楚。
分隔符只要不是替换内容里出现的字符即可。
常见需要转义的字符包括 .、*、[、]、^、$ 等。
比如要把 192.168.1.1 替换成 10.0.0.1,点号在正则里表示任意字符,严格写法是:
sed -i 's/192\.168\.1\.1/10.0.0.1/g' hosts.conf
如果替换内容里包含 &,它代表整个匹配内容,需要写成 \& 才能输出字面量。
涉及用户输入或脚本变量时,变量要用双引号包裹,否则空格和特殊字符会出问题。
另一个容易忽略的点是权限。sed -i 修改文件需要写权限,如果提示 Permission denied,检查当前用户是否有权修改目标文件,或者用 sudo 执行。
对系统关键文件操作前,确认备份已经生成。
替换后如何验证结果
替换完成后不要只看命令有没有报错,要实际检查内容。
用 grep 搜索旧字符串,确认已经不存在:
grep -rn "old_text" .
如果输出为空,说明当前目录下已没有该字符串。
再搜索新字符串,确认替换数量符合预期:
grep -rn "new_text" .
对于配置文件,替换后建议用对应程序做语法检查。
例如 Nginx 执行 nginx -t,PHP 执行 php -l 文件名,确认配置仍然合法。
涉及服务运行时,替换后重启或重载服务,再观察日志有没有异常。
如果发现替换错了,立即用备份恢复:
cp demo.conf.bak demo.conf
恢复后再重新确认命令,缩小文件范围重试。
常见疑问
sed 批量替换会不会改坏文件?
只要替换规则写对了就不会。
风险主要来自两点:一是正则里的特殊字符没有转义,导致匹配范围扩大;
二是没有备份,改错后无法回滚。
先备份、先 dry-run 看输出,是降低风险最直接的办法。
为什么 sed -i 在 macOS 上直接报错?
macOS 自带的是 BSD sed,-i 后面必须跟一个备份后缀参数,写成 sed -i '' 's/old/new/g' file 即可。
Linux 常见的 GNU sed 允许 -i 后直接接表达式。
只替换每行第一次出现的内容怎么写?
去掉 g 标志,使用 sed -i 's/old_text/new_text/' file,这样每行只替换第一处匹配。
替换内容里有斜杠或反斜杠怎么办?
斜杠可以换分隔符,例如用 # 或 |。
反斜杠需要写成 \\ 转义,建议先在测试文件上验证输出,再对真实文件执行。
小结
Linux sed批量替换文本的核心思路是:先用 grep 确认范围,备份文件,再从单文件替换跑通,最后用 find 加 sed 扩展到多文件和递归目录。
特殊字符要转义,分隔符可以按内容替换,改完用 grep 和程序自带的语法检查验证。
掌握这套流程后,改配置、换域名、批量修正路径都能快速完成。