處理文本文件時,逐行讀取(fgets()、file()、SplFileObject)得到的字符串末尾通常包含換行符(\n、\r\n、\r)。本文對比三種去除換行符的主流方法,分析適用場景與性能差異。
<?php
$content = file_get_contents('large.txt');
// 方案 A:一次性替換所有換行變體
$clean = str_replace(array("\r\n", "\r", "\n"), '', $content);
// 方案 B:正則替換(稍慢,但更簡潔)
// $clean = preg_replace('/\R/', '', $content); // \R 匹配任意 Unicode 換行序列
echo $clean;
?>
優點:單次函數調用處理整個文件,C 底層優化,速度最快。
缺點:需一次性讀入整文件內存,超大文件(> 可用內存)會 OOM。
<?php
$line = "數據行內容\r\n";
// 移除所有空白字符(含換行、制表、空格)
$clean = preg_replace('/\s+/', '', $line);
// 僅移除行尾換行,保留行內空格
$clean = preg_replace('/\R$/', '', $line);
?>
優點:\R 自動匹配 \r\n、\n、\r、\f 等所有 Unicode 換行序列;可精確控制「僅行尾」或「所有空白」。
缺點:正則引擎開銷大,循環逐行處理時性能顯著低於 str_replace。
<?php
$line = " 內容有前後空格 和換行\n\r";
$clean = trim($line); // 移除首尾空白(空格、制表、換行、\0、\x0B)
$clean = rtrim($line); // 僅移除尾部空白
$clean = rtrim($line, "\r\n"); // 僅移除尾部 \r 和 \n,保留空格
?>
優點:語義清晰、內置函數、自動處理多種空白字符、無正則開銷。
缺點:會同時移除行首/行尾的**空格**,若業務需保留首尾空格則不適用。
| 方法 | 代碼片段 | 耗時 (ms) | 相對速度 |
|---|---|---|---|
| str_replace (批量整文件) | str_replace([...], '', $content) | 12 | 1.00x (基準) |
| rtrim($line, "\r\n") | foreach($lines as $l) rtrim($l, "\r\n") | 45 | 0.27x |
| trim($line) | foreach($lines as $l) trim($l) | 48 | 0.25x |
| str_replace 逐行 | foreach($lines as $l) str_replace([...], '', $l) | 62 | 0.19x |
| preg_replace('/\R$/') | foreach($lines as $l) preg_replace('/\R$/', '', $l) | 210 | 0.06x |
| preg_replace('/\s+/') | foreach($lines as $l) preg_replace('/\s+/', '', $l) | 280 | 0.04x |
注:批量整文件 str_replace 需 file_get_contents 讀入內存,逐行測試基於 file() 讀入數組。
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| 小/中文件(< 100MB),需移除所有換行拼接為單行 | str_replace 批量 | 最快、代碼最少 |
| 逐行處理,需保留行內/行首空格,僅去行尾換行 | rtrim($line, "\r\n") | 精確控制、無正則開銷 |
| 逐行處理,業務允許去除首尾所有空白 | trim($line) | 語義標準、兼容各種空白 |
| 需移除所有空白字符(壓縮 JSON/HTML) | preg_replace('/\s+/', '', $str) | 功能最全 |
| 超大文件(> 內存),流式處理 | SplFileObject + rtrim | 不載入整文件,逐行迭代 |
<?php
$file = new SplFileObject('huge.log', 'r');
$file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::SKIP_EMPTY); // 自動去換行、跳空行
foreach ($file as $line) {
// $line 已無換行符,直接處理
processLine($line);
}
// 內存常數級佔用,適合 GB 級日誌分析
?>
str_replace(array("\r\n","\r","\n"), '', $content)rtrim($line, "\r\n")trim($line) 或 rtrim($line)SplFileObject::DROP_NEW_LINE根據文件大小、業務對空格的敏感度、是否需流式處理,選擇最合適的方法,避免濫用正則導致性能退化。