grep -rl 命令可高效定位含目标字符串的文件,比python逐个读取快一个数量级;fileinput需设inplace=true才能原地修改,且须用print(..., end="")避免多余换行;处理多编码文件应先试utf-8再降级gbk或latin-1;大文件替换需手动seek+truncate以节省内存。

用 grep 快速定位含目标字符串的文件(Linux/macOS)
直接靠 Python 逐个读文件搜字符串,既慢又容易漏编码问题。先用系统级工具筛出候选文件更高效——grep -rl "旧字符串" ./src/ 能列出所有匹配文件路径,比 Python 自己遍历快一个数量级。
注意点:
-
grep -r默认递归,但遇到二进制文件可能报错,加--binary-files=skip更稳 - 中文或特殊字符记得用单引号包裹字符串,避免 shell 解析错误
- Windows 用户可用
findstr /s /i "旧字符串" *.py,但不支持正则替换,仅作定位
fileinput 原地替换时必须设 inplace=True
Python 自带的 fileinput 是少数能真正“原地修改”文件的方案,但默认只是读取流——漏掉 inplace=True 参数会导致什么都没改,还可能把原文件清空。
典型写法:
import fileinput
<p>with fileinput.input(files=["a.py", "b.py"], inplace=True) as f:
for line in f:
print(line.replace("旧字符串", "新字符串"), end="")
</p>
关键细节:
-
print(..., end="")必须显式指定,否则每行会多一个换行符 -
files参数传的是路径列表,不是通配符(如"*.py"),得先用glob或pathlib构造 - 该操作不可逆,务必提前备份或加
backup=".bak"参数生成备份
处理编码不一致的文件要主动捕获 UnicodeDecodeError
项目里混着 utf-8、gbk、甚至无 BOM 的 utf-8-sig 文件很常见。用 open() 直接读,遇到编码错就崩,而 fileinput 默认用系统编码(Windows 是 cp1252),大概率失败。
稳妥做法是:先尝试 utf-8,失败后降级用 gbk,再失败才跳过:
def safe_read_write(filepath, old, new):
try:
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
with open(filepath, "w", encoding="utf-8") as f:
f.write(content.replace(old, new))
except UnicodeDecodeError:
try:
with open(filepath, "r", encoding="gbk") as f:
content = f.read()
with open(filepath, "w", encoding="gbk") as f:
f.write(content.replace(old, new))
except (UnicodeDecodeError, LookupError):
print(f"跳过无法解码的文件: {filepath}")
注意:gbk 在 Linux 上可能不存在,可换成 latin-1 作为兜底(它不会报错,但中文会变乱码,适合纯英文场景)。
大文件别用 read(),改用逐行 replace + seek 模拟原地改
一个 500MB 的日志文件,read() 一次性加载进内存,Python 进程直接吃满 2GB 内存。这时候不能依赖 fileinput(它内部也是全读),得手动控制 I/O。
思路是:打开文件两次,一次读、一次写,用 seek(0) 和 truncate() 实现覆盖:
with open("huge.log", "r+", encoding="utf-8") as f:
lines = []
for line in f:
lines.append(line.replace("旧", "新"))
f.seek(0)
f.writelines(lines)
f.truncate() # 清掉末尾残留内容
风险点:
- 如果替换后总长度变短,
f.truncate()必须调用,否则旧结尾内容残留 - 不能用
readlines(),它会把整个文件载入内存;上面的for line in f是逐行迭代,内存友好 - 此法只适合“替换不改变行结构”的场景(比如改配置值),不适合跨行正则替换
真正要改二进制文件或做复杂模式替换,老实用 sed -i 或专门工具,Python 不是万能胶水。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











