首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 與 AWK 實現字串壓縮解壓:游程編碼演算法實戰

     編輯:PHP 綜合知識

PHP 與 AWK 實現字串壓縮解壓:游程編碼演算法實戰

游程編碼是最簡單的無損壓縮演算法之一,核心思想是將連續重複的字元替換為「計數 + 字元」的形式。本文提供 PHP 與 AWK 兩種語言的完整實現,適合處理加密後的密文或含大量重複字元的文字資料。

演算法原理

對於輸入字串 AAABBCCCCC,壓縮後為 3A2B5C。解壓時依序讀取數字與字元,重複輸出對應次數。關鍵點:

  • 單一字元不加計數(或計數為 1 時省略)
  • 計數可能多位數(如 12A 表示 12 個 A)
  • 需處理字元本身為數字的情況(解壓時以正則區分)

PHP 實現

壓縮函數

<?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 實現(通用格式)

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 欄位、純文字流

進階優化建議

  1. 雙位元組字元支援:若處理 UTF-8 中文,需用 mb_substr / mb_strlen 並調整正則為 /./u
  2. 逃脫機制:當字元本身為數字時,壓縮端可加前綴(如 !),解壓端識別前綴還原
  3. 串流式 PHP 實現:參考 AWK 邏輯重寫為逐字元迭代,避免正則回調,大幅提升長字串效能

總結

游程編碼雖簡單,但在特定場景(重複度高的加密密文、日誌壓縮)極具價值。PHP 版適合 Web 業務整合,AWK 版適合運維管線處理。理解其核心邏輯後,可根據業務語言環境靈活移植或擴展(如加入霍夫曼編碼進階壓縮)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved