2010-01-13 204 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