glob() 是php批量匹配文件路径最直接方法,支持通配符、返回数组可直接遍历,但需注意工作目录、版本兼容性及递归标志。

用 glob() 批量匹配文件路径最直接
PHP 没有内置“批量清洗”概念,实际就是:遍历一批文件 → 读取内容 → 按规则修改 → 写回或另存。第一步卡住,往往是因为硬写循环拼路径,容易漏掉子目录或忽略隐藏文件。glob() 是最轻量、无依赖的起点,它原生支持通配符,且返回数组可直接 foreach。
常见错误是写成 glob('*.txt') 却没注意当前工作目录(getcwd())不是你预期的目录;或者用 ** 时忘了加 GLOB_BRACE 或 PHP 版本低于 7.3(不支持递归)。
- 固定目录下清洗所有日志:
glob('/var/log/app/*.log') - 跨多级子目录(PHP ≥ 7.3):
glob('/data/inbox/**/*.csv', GLOB_BRACE) - 避免匹配到备份文件:
glob('/tmp/data/*.json') + array_filter(glob('/tmp/data/*.json.*'), fn($f) => !str_ends_with($f, '.bak'))
清洗逻辑别直接 file_get_contents() 全读进内存
单个几百 MB 的日志或 CSV 文件,用 file_get_contents() 会触发 Fatal error: Allowed memory size exhausted。清洗不是重写,多数时候只需逐行处理 —— 尤其是去空行、删注释、替换敏感字段这类操作。
推荐用 fopen() + fgets() 流式读取,配合 file_put_contents(..., FILE_APPEND | LOCK_EX) 累积写入临时文件,最后原子化替换原文件。这样内存占用恒定在几 KB,10GB 文件也不崩。
- 跳过注释行(# 开头):
if (ltrim($line)[0] !== '#') { fwrite($out, $line); } - 敏感词脱敏(如手机号):
preg_replace('/1[3-9]\d{9}/', '1XXXXXXXXX', $line) - 避免覆盖原文件前崩溃:
rename($temp_file, $original_file)替代直接写原路径
mb_convert_encoding() 必须在清洗前统一编码
混合来源的文本文件(比如 Windows 传来的 GBK 日志、Mac 生成的 UTF-8 CSV、旧系统导出的 BIG5 表格),如果跳过编码检测直接 str_replace() 或正则,会出现乱码、匹配失败、甚至截断字符。PHP 的 mb_* 函数默认按 mb_internal_encoding() 解析,而该值常是 UTF-8,和文件实际编码冲突。
不要依赖 mb_detect_encoding() —— 它误判率高,尤其对短文本或纯 ASCII 内容。更可靠的是:明确约定输入编码(如全部转为 UTF-8),用 mb_convert_encoding($content, 'UTF-8', $detected) 显式转换,再清洗。
- 查文件真实编码(命令行辅助):
file -i your_file.txt或iconv -l | grep -i gbk - 强制转 UTF-8(容错模式):
mb_convert_encoding($line, 'UTF-8', 'GBK, BIG5, ASCII, UTF-8') - 清洗后保存时指定 BOM(如需兼容 Excel):
file_put_contents($path, "\xEF\xBB\xBF" . $cleaned_content)
大文件清洗后校验行数和哈希值防静默损坏
批量清洗脚本跑完没报错,不代表结果正确。常见静默问题:某行因正则边界错误被截断、BOM 插入位置错乱导致首行偏移、换行符从 \n 变成 \r\n 导致后续解析失败。人工抽查不可靠,必须自动化校验。
核心是两件事:行数是否守恒(除非明确删除整行),以及关键字段哈希是否一致(如清洗前后每行 MD5 值变化应符合预期)。不要等上线才发现数据少了一半。
- 快速比对行数:
count(file($original)) === count(file($cleaned))(小文件可用;大文件改用exec('wc -l ' . escapeshellarg($file), $out);) - 抽样校验内容一致性(跳过已知变动字段):
md5(substr($line, 0, 20) . substr($line, -20)) - 记录清洗摘要到日志:
file_put_contents('clean.log', date('Y-m-d H:i:s') . " {$file}: {$lines_before}→{$lines_after}\n", FILE_APPEND)
清洗不是越快越好,而是改得准、留得住痕迹、出错能回滚。临时文件命名带时间戳、原文件先 copy() 备份、每步加 is_writable() 检查 —— 这些琐碎动作,比写个炫酷正则重要得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











