2010-01-13 195 views
3

我試圖使用vsprintf()來輸出一個格式化的字符串,但是我需要在運行之前驗證它是否有正確數量的參數,以防止「太少爭論「的錯誤。如何在運行前檢查vsprintf的參數是否正確

從本質上講,我認爲我需要的是一個正則表達式來計算類型說明符的數量,但對於正則表達式我很無用,而且我無法在任何地方爲它提供資金,所以我認爲我會給出一個走。 :)

除非你能想到更好的方法,這個方法是沿着我想要的。

function __insertVars($string, $vars = array()) { 

    $regex = ''; 
    $total_req = count(preg_match($regex, $string)); 

    if($total_req === count($vars)) { 
     return vsprintf($string, $vars); 
    } 

} 

請告訴我,如果你能想到一個更簡單的方法。

回答

4

我認爲你的解決方案是或多或少地可靠地告訴字符串中有多少個參數的唯一方法。

這裏是正則表達式我想到了,與preg_match_all()使用它:

%[-+]?(?:[ 0]|['].)?[a]?\d*(?:[.]\d*)?[%bcdeEufFgGosxX] 

基於sprintf() documentation。應該與PHP 4.0.6+/5兼容。


編輯 - 稍微更緊湊的版本:

%[-+]?(?:[ 0]|'.)?a?\d*(?:\.\d*)?[%bcdeEufFgGosxX] 

同時,充分利用func_get_args()func_num_args()功能在你的代碼。


編輯: - 更新支持位置/交換參數(沒有測試):

function validatePrintf($format, $arguments) 
{ 
    if (preg_match_all("~%(?:(\d+)[$])?[-+]?(?:[ 0]|['].)?(?:[-]?\d+)?(?:[.]\d+)?[%bcdeEufFgGosxX]~", $format, $expected) > 0) 
    { 
     $expected = intval(max($expected[1], count(array_unique($expected[1])))); 

     if (count((array) $arguments) >= $expected) 
     { 
      return true; 
     } 
    } 

    return false; 
} 

var_dump(validatePrintf('The %2$s contains %1$d monkeys', array(5, 'tree'))); 
+0

完美的作品,謝謝。 – rich97 2010-01-13 02:30:35

+0

rich97沒問題。 – 2010-01-13 02:36:48

+0

但是如果'format ='%3 $ s''時函數的內容類似'vsprintf(format,args)'呢? – lmojzis 2013-06-05 02:01:49

0

我用阿利克斯阿克塞爾答案,並創建通用的功能。

我們有$ countArgs(來自函數參數)和$ countVariables(來自$格式,如%s)。 例如:

$object->format('Hello, %s!', ['Foo']); // $countArgs = 1, $countVariables = 1; 

打印:你好,Foo!

$object->format('Hello, %s! How are you, %s?', ['Bar']); // $countArgs = 1, $countVariables = 2; 

打印:錯誤。

功能:

public static function format($format, array $args) 
{ 
    $pattern = "~%(?:(\d+)[$])?[-+]?(?:[ 0]|['].)?(?:[-]?\d+)?(?:[.]\d+)?[%bcdeEufFgGosxX]~"; 

    $countArgs = count($args); 
    preg_match_all($pattern, $format, $expected); 
    $countVariables = isset($expected[0]) ? count($expected[0]) : 0; 

    if ($countArgs !== $countVariables) { 
     throw new \Exception('The number of arguments in the string does not match the number of arguments in a template.'); 
    } else { 
     return $countArgs > 1 ? vsprintf($format, $args) : sprintf($format, reset($args)); 
    } 
} 
+0

你可以添加更多的解釋嗎? – Shawn 2016-08-02 18:57:38

+0

@Shawn是的,我添加了一條評論。 – 2016-08-03 19:45:41

+0

我相信'vsprintf()'允許'%%'代表一個'%'?我不認爲這個正則表達式允許這樣做 – Sam 2018-01-05 14:46:46

相關問題