當前位置: 首頁> 最新文章列表> 如何實現類似sprintf 的自定義格式化函數

如何實現類似sprintf 的自定義格式化函數

gitbox 2025-04-28

在PHP 中, sprintf函數是一個強大的字符串格式化工具,能夠將變量以指定格式插入字符串中。例如:

 $name = "Alice";
$age = 30;
echo sprintf("我的名字是 %s,今年 %d 歲。", $name, $age);

輸出為:

 我的名字是 Alice,今年 30 歲。

雖然sprintf已經非常實用,但有時我們可能希望更靈活地控制格式化方式,或者在某些框架或環境下實現一個“輕量版”或者“可定製版”的格式化函數。本文將介紹如何用PHP 自定義一個類似sprintf的格式化函數。

一、目標功能

我們希望實現一個函數my_sprintf($template, $args) ,其支持以下功能:

  • 替換佔位符,如%s%d

  • 支持順序傳參或數組傳參;

  • 保持良好的可讀性與可維護性。

二、基礎實現

我們從一個簡單的實現開始,僅支持%s%d

 function my_sprintf($template, ...$args) {
    $argIndex = 0;
    $result = preg_replace_callback('/%[sd]/', function($matches) use (&$args, &$argIndex) {
        $placeholder = $matches[0];
        $value = $args[$argIndex++] ?? '';

        if ($placeholder === '%d') {
            return intval($value);
        } elseif ($placeholder === '%s') {
            return strval($value);
        } else {
            return $placeholder;
        }
    }, $template);

    return $result;
}

使用示例:

 echo my_sprintf("歡迎 %s,您有 %d 條新消息。", "Alice", 5);

輸出:

 歡迎 Alice,您有 5 條新消息。

三、支持數組作為參數傳入

如果我們想讓這個函數也支持將參數以數組形式傳入,可以稍作修改:

 function my_sprintf_array($template, array $args) {
    $argIndex = 0;
    $result = preg_replace_callback('/%[sd]/', function($matches) use (&$args, &$argIndex) {
        $placeholder = $matches[0];
        $value = $args[$argIndex++] ?? '';

        return match ($placeholder) {
            '%d' => intval($value),
            '%s' => strval($value),
            default => $placeholder,
        };
    }, $template);

    return $result;
}

使用示例:

 echo my_sprintf_array("請訪問 https://gitbox.net/user/%s,積分:%d", ["alice", 100]);

輸出:

 請訪問 https://gitbox.net/user/alice,積分:100

四、進一步擴展(支持帶寬度和填充)

我們還可以進一步支持格式如%05d (寬度為5,左側補零):

 function my_sprintf_extended($template, ...$args) {
    $argIndex = 0;
    $result = preg_replace_callback('/%0?(\d*)([sd])/', function($matches) use (&$args, &$argIndex) {
        $width = (int)($matches[1] ?? 0);
        $type = $matches[2];
        $value = $args[$argIndex++] ?? '';

        if ($type === 'd') {
            $formatted = str_pad(intval($value), $width, '0', STR_PAD_LEFT);
        } else {
            $formatted = strval($value);
        }

        return $formatted;
    }, $template);

    return $result;
}

使用示例:

 echo my_sprintf_extended("訂單號:%05d,用戶:%s", 42, "bob");

輸出:

 訂單號:00042,用戶:bob

五、總結

通過上述幾個版本的實現,我們可以看到:

  • 自定義格式化函數讓我們可以根據業務需要靈活控制;

  • 利用正則表達式結合回調函數,是實現類似sprintf的關鍵;

  • 若需更複雜格式(如浮點、進制、佔位順序等),可繼續擴展正則表達式的解析規則。

在實際項目中,這類函數也常用於自定義模板引擎、日誌記錄系統或DSL(領域特定語言)開發中,為開髮帶來更多便利與控制力。

你可以將這個函數封裝進自己的工具庫中,在類似https://gitbox.net這樣的項目中使用,提升開發效率。