處理無換行符的大文件(如 10MB 單行)時,sed 預設按行讀入內存導致極慢甚至 OOM。本文分析原因,給出正確用法與替代工具。
# 錯誤用法:管道輸入導致 sed 按行處理,單行 10MB 直接撐爆內存
cat aaa | sed 's/stra/strb/g' > bbb
sed 核心機制:逐行讀取 → 模式空間處理 → 輸出cat | sed 額外增加進程間拷貝開銷
sed 's/stra/strb/g' aaa > bbb
aaa,避免管道開銷bbb
sed -i 's/stra/strb/g' aaa
-i 就地編輯(BSD sed 需 -i '')
# 錯誤
sed -s "/s/stra/strb/g" aaa > bbb
# 正確(無 -s,無雙引號包裹腳本,斜槓作分隔符)
sed 's/stra/strb/g' aaa > bbb
# 僅適合單字符替換,如 a->b
tr 'a' 'b' < aaa > bbb
# 流式處理,不載入整文件,支持複雜正則
perl -pe 's/stra/strb/g' aaa > bbb
# 就地修改
perl -pi -e 's/stra/strb/g' aaa
awk '{gsub(/stra/, "strb"); print}' aaa > bbb
# replace.py
import sys
CHUNK = 1024 * 1024 # 1MB 塊
with open(sys.argv[1], 'r') as fin, open(sys.argv[2], 'w') as fout:
while True:
chunk = fin.read(CHUNK)
if not chunk:
break
fout.write(chunk.replace('stra', 'strb'))
# 使用
python3 replace.py aaa bbb
| 工具 | 耗時 | 內存峰值 | 適用場景 |
|---|---|---|---|
| sed(管道) | ~45s | ~500MB | 錯誤用法 |
| sed(直接) | ~0.8s | ~20MB | 標準替換、就地修改 |
| perl | ~0.6s | ~15MB | 複雜正則、流式 |
| python(分塊) | ~0.5s | ~2MB | 超大文件、邏輯複雜 |
| tr | ~0.1s | ~1MB | 單字符映射 |
sed -i:原子性、無臨時文件殘留tr:極致性能cp aaa aaa.bak 再操作sed 本身不慢,慢在錯誤的管道用法和無換行符導致單行過大。正確用法 sed 's/old/new/g' file 或 sed -i 's/old/new/g' file 即可解決 90% 場景。極端大文件轉用 Python 分塊或 Perl 流式處理。