Calcifer Calcifer 2 Calcifer 3 Calcifer 4
Linux

sed全局替换

2018/09/13 15:48 6773 次阅读 王梓
打赏
✸ ✸ ✸

sed 替换基础语法

sed(Stream Editor)是 Linux 下最强大的文本处理工具之一。它的替换功能用得最多,核心语法:

sed 's/旧字符串/新字符串/标志' 文件名

其中 s 表示替换(substitute),标志位控制替换行为。

替换标志详解

标志含义示例
无标志只替换每行第一个匹配sed 's/a/b/' file
g替换每行所有匹配(全局)sed 's/a/b/g' file
i忽略大小写sed 's/hello/world/gi' file
2只替换每行第2个匹配sed 's/a/b/2' file
p打印替换后的行sed -n 's/a/b/p' file

-i 参数:直接修改文件

默认 sed 只输出结果不改文件。加 -i 直接修改原文件(危险操作,建议先备份):

# 直接修改文件(Linux)
sed -i 's/https/http/g' config.txt

# macOS 需要指定备份后缀(空字符串表示不备份)
sed -i '' 's/https/http/g' config.txt

# 建议:先备份再替换
sed -i.bak 's/https/http/g' config.txt   # 自动生成 config.txt.bak

批量替换多个文件

结合 find 命令,可以递归替换目录下所有匹配文件:

# 替换当前目录下所有 .conf 文件中的 https 为 http
sed -i 's/https/http/g' $(find ./ -name '*.conf')

# 更安全的写法(处理文件名含空格的情况)
find ./ -name '*.conf' -exec sed -i 's/https/http/g' {} \;

# 或者用 xargs(性能更好)
find ./ -name '*.conf' | xargs sed -i 's/https/http/g'

# 只替换 .py 文件中的 print 语句
find ./ -name '*.py' -exec sed -i 's/print \(.*\)/print(\1)/g' {} \;

高级用法

使用不同的分隔符

当替换内容包含 / 时,可以用其他字符做分隔符:

# 替换路径中的 / 很麻烦
sed -i 's/\/usr\/local\/bin/\/opt\/bin/g' file

# 用 # 或 | 做分隔符,清爽很多
sed -i 's#/usr/local/bin#/opt/bin#g' file
sed -i 's|/usr/local/bin|/opt/bin|g' file

正则表达式替换

# 删除行首空格
sed -i 's/^[ \t]*//' file

# 删除空行
sed -i '/^$/d' file

# 删除注释行(# 开头)
sed -i '/^#/d' file

# 在每行末尾加分号
sed -i 's/$/ ;/' file

# 提取 IP 地址所在行
sed -n '/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/p' file

指定行范围替换

# 只替换第3行
sed -i '3s/old/new/g' file

# 替换第2到5行
sed -i '2,5s/old/new/g' file

# 替换最后一行
sed -i '$s/old/new/g' file

# 从匹配行开始替换到文件末尾
sed -i '/START/,$s/old/new/g' file

多条替换命令

# 用 -e 串联多条命令
sed -i -e 's/foo/bar/g' -e 's/hello/world/g' file

# 或者用分号
sed -i 's/foo/bar/g; s/hello/world/g' file

实战场景

场景1:批量修改配置文件中的域名

# 迁移服务器时批量替换域名
find /etc/nginx/conf.d/ -name '*.conf' \
  -exec sed -i 's/old-domain.com/new-domain.com/g' {} \;

# 验证替换结果
grep -r 'old-domain.com' /etc/nginx/conf.d/   # 应该无输出
grep -r 'new-domain.com' /etc/nginx/conf.d/   # 确认新域名

场景2:修改 MySQL 配置

# 修改 max_connections
sed -i 's/^max_connections.*/max_connections = 500/' /etc/my.cnf

# 如果配置项不存在则追加
grep -q 'max_connections' /etc/my.cnf || echo 'max_connections = 500' >> /etc/my.cnf

场景3:处理 CSV 数据

# 将 CSV 的逗号分隔改为 Tab 分隔
sed -i 's/,/\t/g' data.csv

# 删除 CSV 第一行(表头)
sed -i '1d' data.csv

# 在第一行前插入新表头
sed -i '1i\id,name,email,phone' data.csv

sed 替换流程

读取一行 --> 模式匹配? --是--> 执行替换 --> 输出结果
                |                              |
                否                          有 -i ?
                |                           /    \
            直接输出                       是      否
                                          |       |
                                      写回文件  输出到终端

常见踩坑

  • sed -i 在 macOS 和 Linux 上行为不同,macOS 必须加备份后缀参数
  • 替换内容包含 & 时需要转义(\&),因为 & 在 sed 中代表匹配到的内容
  • 使用变量时要用双引号:sed -i "s/$OLD/$NEW/g" file
  • 处理大文件时 sed -i 会创建临时文件,确保磁盘空间充足

总结

sed 替换的核心就是 s/old/new/g-i。配合 find 做批量替换,配合正则做复杂匹配,基本能覆盖日常 90% 的文本处理需求。

✸ ✸ ✸

📜 版权声明

本文作者:王梓 | 原文链接:https://www.bthlt.com/note/11-sed全局替换

出处:葫芦的运维日志 | 转载请注明出处并保留原文链接

📜 留言板

留言提交后需管理员审核通过才会显示