处理大文件须流式逐行读取并用预编译正则匹配,避免内存溢出;输出用newline=''和print(line, end='', file=f)确保换行正确,调试优先验证正则与样本数据。

用 re.search() 逐行匹配,别读全文件
大文件(比如几个 GB 的日志)不能用 readlines() 或 read(),内存会爆。必须流式处理:打开、逐行读、判断、写入。核心是用 re.search()(或 re.match())做单行正则判断,不是用 re.findall() 去全文搜——后者得先把整段文本加载进来。
常见错误现象:MemoryError、程序卡死、Python 进程占用几十 GB 内存;或者误用 re.search(pattern, whole_text) 把整个文件当一个字符串传进去。
- 用
with open(...)上下文管理器,确保文件句柄及时释放 - 正则 pattern 尽量具体,避免
.*开头导致回溯爆炸(尤其对超长行) - 如果只需匹配开头,优先用
re.match(),比re.search()略快且语义更清 - 编译正则:用
re.compile(r'your_pattern')一次,循环里复用,别在 for 里反复调re.search(r'...', line)
写入时用 newline='' 避免 Windows 换行错乱
不加这个参数,在 Windows 上用 'w' 模式写文本,Python 默认把 \n 转成 \r\n,如果原文件是 Unix 换行(\n),结果每行会多出一个 \r,可能影响下游解析。
使用场景:跨平台处理日志、CSV、JSONL 等纯文本格式;尤其是后续还要用 shell 工具(如 grep、awk)继续处理新文件时。
立即学习“Python免费学习笔记(深入)”;
- 输入文件按原样读(默认
newline=None,能兼容各种换行) - 输出文件显式指定
newline='',让print()或f.write()不做额外转换 - 如果写的是二进制内容(比如带 \0 的日志),直接开
'wb',但正则匹配得先 decode —— 这种情况建议先确认编码,别硬上
print(line, file=out_f) 比 out_f.write(line) 更安全
看起来只差一点点,但实际行为不同:write() 要求你手动保证 line 结尾有换行符;而 print() 自动补(且受 newline='' 控制),不会把两行粘一起,也不会多出空行。
容易踩的坑:原文件某行末尾没 \n(比如最后一行被截断),用 write(line) 直接写进去,新文件就少了个换行;或者你写了 write(line.rstrip('\n') + '\n'),但忘了 line 可能是空字符串或只有 \r。
- 统一用
print(line, end='', file=out_f)—— 显式控制结尾,和newline=''配合最稳 - 如果
line是从for line in f:来的,它自带换行符,别再.rstrip()后又加\n - 不要用
f.writelines()批量写,它不自动加分隔符,容易丢换行
过滤后为空怎么办?检查正则是否真能匹配
跑完发现输出文件是空的,不是代码错了,大概率是正则写崩了:太严格、大小写没注意、转义漏了、或者目标字段根本不在当前行(比如想匹配 JSON 字段却在多行结构里)。
调试建议:先取前 10 行样本,用 re.search(pattern, sample_line) 手动试;别直接跑全量。
- 用
re.escape()包裹动态拼接的字符串部分,比如路径、用户名 - pattern 中用
(?i)开头开启忽略大小写,比每个字母写[aA][bB]干净 - 测试时加个计数器:匹配成功就
print('hit:', line[:50]),一眼看出哪类行被捞到了 - 注意 Python 正则默认不支持
\d匹配 Unicode 数字,如果文件含中文数字,得加re.ASCII标志或改用[0-9]
真正麻烦的永远不是“怎么写”,而是“为什么这行没被匹配到”——正则写得越短,越要盯着原始数据看三遍。










