處理日誌去重、清單去重等場景時,需要高效刪除文本文件中的重複行。本文提供兩個通用函數:RemoveDuplicatedLines() 直接操作檔案,RemoveDuplicatedLinesByString() 處理字串,支援大小寫忽略、自定義分隔符、記憶體友善。可直接納入工具庫。
<?php
/**
* 移除字串中重複的行
*
* @param string $lines 輸入字串
* @param bool $ignoreCase 是否忽略大小寫
* @param string $newLine 行分隔符,預設 "\n"
* @return string 去重後字串
*/
function RemoveDuplicatedLinesByString(string $lines, bool $ignoreCase = false, string $newLine = "\n"): string {
// 陣列輸入自動轉字串
if (is_array($lines)) {
$lines = implode($newLine, $lines);
}
$lines = explode($newLine, $lines);
$uniqueLines = [];
$duplicateCount = 0;
foreach ($lines as $line) {
$currentLine = trim($line);
if ($currentLine === '') continue; // 跳過空行
$key = $ignoreCase ? strtolower($currentLine) : $currentLine;
if (!isset($uniqueLines[$key])) {
$uniqueLines[$key] = $currentLine; // 保留首次出現的原始大小寫
} else {
$duplicateCount++;
}
}
// 可選:排序保持穩定輸出
// ksort($uniqueLines); // 按 key 排序
// asort($uniqueLines); // 按 value 排序
return implode($newLine, array_values($uniqueLines));
}
?>
<?php
/**
* 直接處理檔案:讀取 → 去重 → 覆寫
*
* @param string $filepath 檔案路徑
* @param bool $ignoreCase 忽略大小寫
* @param string $newLine 行分隔符
* @return int 移除的重複行數
* @throws Exception 檔案不存在或不可寫
*/
function RemoveDuplicatedLines(string $filepath, bool $ignoreCase = false, string $newLine = "\n"): int {
if (!file_exists($filepath)) {
throw new Exception("RemoveDuplicatedLines error: File '{$filepath}' does not exist!");
}
$content = file_get_contents($filepath);
if ($content === false) {
throw new Exception("RemoveDuplicatedLines error: Cannot read file '{$filepath}'!");
}
$newContent = RemoveDuplicatedLinesByString($content, $ignoreCase, $newLine);
$removedCount = substr_count($content, $newLine) - substr_count($newContent, $newLine); // 近似計算
if (!is_writable($filepath)) {
throw new Exception("RemoveDuplicatedLines error: File '{$filepath}' is not writable!");
}
$bytes = file_put_contents($filepath, $newContent);
if ($bytes === false) {
throw new Exception("RemoveDuplicatedLines error: Failed to write file '{$filepath}'!");
}
return $removedCount;
}
?>
<?php
// 範例 1:基本去重
$removed = RemoveDuplicatedLines('data.txt');
echo "已移除 {$removed} 行重複內容\n";
// 範例 2:忽略大小寫去重 (Apple, apple 視為同一行)
RemoveDuplicatedLines('data.txt', true);
// 範例 3:自定義分隔符 (分號分隔的單行資料)
$singleLine = 'foo;bar;foo;foo;baz';
$deduped = RemoveDuplicatedLinesByString($singleLine, false, ';');
echo $deduped; // foo;bar;baz
// 範例 4:處理陣列輸入
$arr = ['line1', 'line2', 'line1', 'line3'];
echo RemoveDuplicatedLinesByString($arr); // line1\nline2\nline3
?>
sort -u 系統指令)。<?php
function RemoveDuplicatedLinesKeepLast(string $lines, bool $ignoreCase = false, string $newLine = "\n"): string {
$arr = is_array($lines) ? $lines : explode($newLine, $lines);
$map = [];
// 反向遍歷,後出現的覆蓋先出現的
for ($i = count($arr) - 1; $i >= 0; $i--) {
$line = trim($arr[$i]);
if ($line === '') continue;
$key = $ignoreCase ? strtolower($line) : $line;
if (!isset($map[$key])) {
$map[$key] = $line;
}
}
return implode($newLine, array_reverse(array_values($map)));
}
?>
根據業務需求選擇保留首次或最後出現,工具函數靈活應對。