游程編碼是最簡單的無損壓縮演算法之一,核心思想是將連續重複的字元替換為「計數 + 字元」的形式。本文提供 PHP 與 AWK 兩種語言的完整實現,適合處理加密後的密文或含大量重複字元的文字資料。
對於輸入字串 AAABBCCCCC,壓縮後為 3A2B5C。解壓時依序讀取數字與字元,重複輸出對應次數。關鍵點:
<?php
// $replacement 為需壓縮的目標字元集合(來自上游加密替換表)
function compress_func($match) {
return strlen($match[0]) . $match[0]{0};
}
function compress($str) {
$i = 0;
$pattern = array();
// 為每個目標字元建立匹配「連續 2 次以上」的正則
while (isset($replacement{$i})) {
array_push($pattern, "/".$replacement{$i++}."{2,}/");
}
return preg_replace_callback($pattern, "compress_func", $str);
}
關鍵技巧:動態建立正則陣列,針對特定字元集合進行「連續重複」匹配,避免對非目標字元處理。
function uncompress_func($match) {
return str_repeat($match[2], $match[1]);
}
function uncompress($str) {
// 匹配:一或多位數字 + 任意單一字元
return preg_replace_callback("/(\d+)(\w)/", "uncompress_func", $str);
}
正則 (\d+)(\w) 確保正確解析多位數計數。\w 匹配字母、數字、底線,若目標字元集含特殊符號需調整為 . 或具體字元類別。
AWK 版本適合在 Shell 管線中直接處理文字流,無外部依賴。
#!/bin/awk
function compress(str, _ARGVEND_, str_out, str_len, i, s, l) {
str_out = "";
str_len = length(str);
s = "";
l = 1;
for (i = 1; i <= str_len; i++) {
if (substr(str, i, 1) == s) {
l++;
} else {
if (s != "") {
if (l > 1) str_out = str_out "" l;
str_out = str_out "" s;
}
s = substr(str, i, 1);
l = 1;
}
}
# 處理最後一組
if (s != "") {
if (l > 1) str_out = str_out "" l;
str_out = str_out "" s;
}
return str_out;
}
function uncompress(str, _ARGVEND_, str_out, str_len, i, c) {
str_out = "";
str_len = length(str);
for (i = 1; i <= str_len; i++) {
c = 0;
# 讀取連續數字構成計數
while (substr(str, i, 1) ~ /[0-9]/) {
c = c * 10 + substr(str, i, 1);
i++;
}
if (c < 1) c = 1; # 無數字預設為 1
# 輸出對應次數字元
while (c--) str_out = str_out "" substr(str, i, 1);
}
return str_out;
}
<?php
$replacement = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
$original = "AAABBBCCCCCCDDDEEEEE";
$compressed = compress($original);
echo "原始: $original\n";
echo "壓縮: $compressed\n";
echo "解壓: " . uncompress($compressed) . "\n";
// 輸出:
// 原始: AAABBBCCCCCCDDDEEEEE
// 壓縮: 3A3B6C3D5E
// 解壓: AAABBBCCCCCCDDDEEEEE
?>
| 指標 | PHP 版本 | AWK 版本 |
|---|---|---|
| 執行環境 | Web 請求、CLI 腳本 | Shell 管線、批次處理 |
| 處理速度 | 中等(正則回調開銷) | 極快(原生字串操作) |
| 記憶體佔用 | 較高(載入整字串) | 極低(流式處理) |
| 適用資料 | 加密密文、Base64 編碼後資料 | 日誌檔、CSV 欄位、純文字流 |
mb_substr / mb_strlen 並調整正則為 /./u!),解壓端識別前綴還原游程編碼雖簡單,但在特定場景(重複度高的加密密文、日誌壓縮)極具價值。PHP 版適合 Web 業務整合,AWK 版適合運維管線處理。理解其核心邏輯後,可根據業務語言環境靈活移植或擴展(如加入霍夫曼編碼進階壓縮)。