字符串函数
在线手册:中文 英文
PHP手册

vsprintf

(PHP 4 >= 4.1.0, PHP 5)

vsprintf返回格式化字符串

说明

string vsprintf ( string $format , array $args )

作用与 sprintf() 函数类似,但是接收一个数组参数,而不是一系列可变数量的参数。

参数

format

关于 format 的描述,参见 sprintf()

args

返回值

根据 formatsprintf() 函数文档中有相关描述)参数指定的格式,在一个字符串中返回一系列值。

范例

Example #1 vsprintf(): 前导 0 的整数

<?php
print vsprintf("%04d-%02d-%02d"explode('-''1988-8-1')); // 1988-08-01
?>

参见


字符串函数
在线手册:中文 英文
PHP手册
PHP手册 - N: 返回格式化字符串

用户评论:

strata_ranger at hotmail dot com (29-Jun-2010 07:15)

Here's a simple variation on vsprintf() suitable for use with database queries where the results were retrieved as an associative array keyed by column names.

<?php

function dbsprintf($format, $fields, $row)
// $format - sprintf() compatible format string
// $row - Array containing key/value pairs of data
// $fields - Array containing key names (from $row) that are to be used as arguments
{
 
// Loop through $fields and insert the corresponding values from $row
 
foreach($fields as &$value)
  {
   
$value = $row[$value];
  } unset(
$value);
 
 
// Format the string and return
 
return vsprintf($format, $fields);
}

// Some data
$row = Array('id' => '12', 'name' => 'World');

// Outputs "Hello World!"
echo dbsprintf('Hello, %s!', Array('name'), $row);
// Outputs "Hello 12!"
echo dbsprintf('Hello, %s!', Array('id'), $row);

?>

jeppe dot dyrby at gmail dot com (04-Mar-2009 12:52)

Heres a new version of the vnsprintf function, i call it dsprintf, but that should matter.

<?php
function dsprintf() {
 
$data = func_get_args(); // get all the arguments
 
$string = array_shift($data); // the string is the first one
 
if (is_array(func_get_arg(1))) { // if the second one is an array, use that
   
$data = func_get_arg(1);
  }
 
$used_keys = array();
 
// get the matches, and feed them to our function
 
$string = preg_replace('/\%\((.*?)\)(.)/e',
   
'dsprintfMatch(\'$1\',\'$2\',\$data,$used_keys)',$string);
 
$data = array_diff_key($data,$used_keys); // diff the data with the used_keys
 
return vsprintf($string,$data); // yeah!
}

function
dsprintfMatch($m1,$m2,&$data,&$used_keys) {
  if (isset(
$data[$m1])) { // if the key is there
   
$str = $data[$m1];
   
$used_keys[$m1] = $m1; // dont unset it, it can be used multiple times
   
return sprintf("%".$m2,$str); // sprintf the string, so %s, or %d works like it should
 
} else {
    return
"%".$m2; // else, return a regular %s, or %d or whatever is used
 
}
}
$str = "Hello, %(place)s, how is it hanning at %(place)s? %s works just as well";
$find = array(
 
'place' => 'world',
 
'sprintf',
 
'not used'
);
echo
dsprintf($str, $find);
// 'Hello, world, how is it hanning at world? sprintf works just as well'
?>

www dot wesley at gmail dot com (15-Nov-2008 08:02)

Here's the new version of vnsprintf()

Thanks to "César K?stli" and "Jan Ulrych"

<?php
function vnsprintf( $format, array $data)
{
   
preg_match_all( '/ (?<!%) % ( (?: [[:alpha:]_-][[:alnum:]_-]* | ([-+])? [0-9]+ (?(2) (?:\.[0-9]+)? | \.[0-9]+ ) ) ) \$ [-+]? \'? .? -? [0-9]* (\.[0-9]+)? \w/x', $format, $match, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
   
$offset = 0;
   
$keys = array_keys($data);
    foreach(
$match as &$value )
    {
        if ( (
$key = array_search( $value[1][0], $keys, TRUE) ) !== FALSE || ( is_numeric( $value[1][0] ) && ( $key = array_search( (int)$value[1][0], $keys, TRUE) ) !== FALSE) )
        {
           
$len = strlen( $value[1][0]);
           
$format = substr_replace( $format, 1 + $key, $offset + $value[1][1], $len);
           
$offset -= $len - strlen( 1 + $key);
        }
    }
    return
vsprintf( $format, $data);
}

$example = array(
   
0 => 'first',
   
'second' => 'second',
   
'third',
   
4.2 => 'fourth',
   
'fifth',
    -
6.7 => 'sixth',
   
'seventh',
   
'eighth',
   
'9' => 'ninth',
   
'tenth' => 'tenth',
   
'-11.3' => 'eleventh',
   
'twelfth'
);

echo
vnsprintf( '%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s %12$s<br />', $example); // acts like vsprintf
echo vnsprintf( '%+0$s %second$s %+1$s %+4$s %+5$s %-6.5$s %+6$s %+7$s %+9$s %tenth$s %-11.3$s %+10$s<br />', $example);
?>

jan dot ulrych at gmail dot com (14-Jul-2008 09:45)

Thanks a lot for vnsprintf function.

However, there is a little bug which occurs only when the  number of parameters in the $data is greater than 10.

The replacement is not performed correctly when two or more replacements should be performed. When the referenced parameter is at position greater or equal to 10 in $data array and it precedes any other referenced parameter in $format string then the subsequent replacement(s) are not performed correctly.

The $offset value should be calculated as
 $offset -= $len - strlen( 1 + $key);

as we substitute string (or float) identifier in the original $format string by value 1 + $key, not $key.

www dot wesley at gmail dot com (16-Jun-2008 09:56)

vnsprintf is equal to vsprintf except for associative, signed or floating keys.

vnsprintf supports for example "%assocKey$05d", "%-2$'+10s" and "%3.2$05u", vsprintf doesn't

vnsprintf( '%2$d', $array) [2nd value] is equal to vsprintf( '%2$d', $array) [2nd value]
vnsprintf( '%+2$d', $array) [key = 2] is equal to vnsprintf( '%2.0$d', $array) [key = 2]
vnsprintf( '%+2$d', $array) [key = 2] is different of vsprintf( '%+2$d', $array) [unsupported]

When you use signed or floating keys, vnsprintf searchs for the signed truncated key of the original array

Note?: vnsprintf does not support for example "%someKeyf" (floating number, key = someKey) or "%+03d" (signed decimal number, key = 3), you should use "%someKey$f" or "%+03$d" respectively.
Note?: "%+03d" (or "%1$+03d") will be interpreted as signed zero-padded decimal number

<?php
function vnsprintf( $format, array $data)
{
   
preg_match_all( '/ (?<!%) % ( (?: [[:alpha:]_-][[:alnum:]_-]* | ([-+])? [0-9]+ (?(2) (?:\.[0-9]+)? | \.[0-9]+ ) ) ) \$ [-+]? \'? .? -? [0-9]* (\.[0-9]+)? \w/x', $format, $match, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
   
$offset = 0;
   
$keys = array_keys($data);
    foreach (
$match as &$value )
    {
        if ( (
$key = array_search( $value[1][0], $keys) ) !== FALSE || ( is_numeric( $value[1][0]) && ( $key = array_search( (int)$value[1][0], $keys) ) !== FALSE ) ) {
           
$len = strlen( $value[1][0]);
           
$format = substr_replace( $format, 1 + $key, $offset + $value[1][1], $len);
           
$offset -= $len - strlen( $key);
        }
    }
    return
vsprintf( $format, $data);
}

$examples = array(
   
2.8=>'positiveFloat',    // key = 2 , 1st value
   
-3=>'negativeInteger',    // key = -3 , 2nd value
   
'my_name'=>'someString'    // key = my_name , 3rd value
);

echo
vsprintf( "%%my_name\$s = '%my_name\$s'\n", $examples);    // [unsupported]
echo vnsprintf( "%%my_name\$s = '%my_name\$s'\n", $examples);    // output : "someString"

echo vsprintf( "%%2.5\$s = '%2.5\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%2.5\$s = '%2.5\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%+2.5\$s = '%+2.5\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%+2.5\$s = '%+2.5\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%-3.2\$s = '%-3.2\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%-3.2\$s = '%-3.2\$s'\n", $examples);        // output : "negativeInteger"

echo vsprintf( "%%2\$s = '%2\$s'\n", $examples);            // output : "negativeInteger"
echo vnsprintf( "%%2\$s = '%2\$s'\n", $examples);            // output : [= vsprintf]

echo vsprintf( "%%+2\$s = '%+2\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%+2\$s = '%+2\$s'\n", $examples);        // output : "positiveFloat"

echo vsprintf( "%%-3\$s = '%-3\$s'\n", $examples);        // [unsupported]
echo vnsprintf( "%%-3\$s = '%-3\$s'\n", $examples);        // output : "negativeInteger"
?>

iisys_ at hotmail dot com (19-Nov-2006 06:29)

I've made this simple function for more compatibility with different applications.
As arguments, it can accept an array or single arguments.

<?php
function asprintf() {
   
$a = func_get_args();
   
$format = array_shift($a);
    if (
is_array($a[0])) {
       
$a = $a[0];
    }
    return
vsprintf($format, $a);
}

# Examples.

$sql_arguments = array('fields' => '*', 'table' => 'users', 'field' => 'user', 'value' => 'exploited');

echo
asprintf("SELECT %s FROM %s WHERE %s = '%s'", $sql_arguments);
# Would output: SELECT * FROM users WHERE user = 'exploited'

echo asprintf("SELECT %s FROM %s WHERE %s = '%s'", '*', 'users', 'user', 'exploited');
# Would output the same.
?>

Roadster (01-Oct-2006 03:44)

Please note: The same functionality (sortof) can be attained between version 4.0.4 and 4.1.0 using call_user_func_array.

Example:

call_user_func_array("sprintf", $arg)

First element of $arg is the format. This rescued me in a situation where version 4.1.0 wasn't available.

jon at ardentcreative dot co dot uk (17-Feb-2006 11:56)

This can be used for quick and dirty internationalization:

<?php
$GLOBALS
['strings']['example'] = "There are %d people.";

// Loads a phrase from the translations list in lang/$lang/phrases.php
function t() {
   
$args = func_get_args();
   
$nArgs = func_num_args();
   
   
$phrase = array_shift($args);
   
$nArgs--;
   
    include_once(
"../lang/" . lang() . "/phrases.php");
    if (isset(
$GLOBALS['strings'][$phrase])) {
        return
vsprintf($GLOBALS['strings'][$phrase], $args);
    } else {
        return
'<span style="color: #ff0000">Untranslated string: ' . $phrase . '</span>';
    }
}
?>

toneee at g mail dot com (19-Dec-2005 05:27)

I found this function to be useful for formatting sql queries.

I do something like this:

function sql_build($template, $params = array()) {
  global $sql_templates;
  if (isset($sql_templates[$template])) {
    $sql = vsprintf($sql_templates[$template], $params);
    return $sql;
  }
  return false;
}

// Fetch list of contacts, for a given section id
$sql_templates['contacts_by_section'] = <<<ENDSQL
select
  id,
  name,
  email, 
  address,
  photo_id
from
  contacts
where
  section_id = %d
ENDSQL;

You also give yourself an added layer of security on the sql due to the sprintf formatting. For example, using %d will not allow any sql injection for that parameter.

tbS dot P dot A dot M at S dot U dot K dot Staylorbarstow dot com (01-Mar-2005 07:49)

Simple but useful routine:

<?php
function vsprintf_iter($fmt,$data) {
    if (!
is_array($data)) return false;
   
$ret = '';
    foreach (
$data as $d) {
       
$ret .= vsprintf($fmt,$d);
    }
    return
$ret;
}
?>

jed at NOSPAM dot jed dot bz (23-May-2004 02:48)

vsprintf() accepts arrays with any keys, so the array_shift() technique is unnecessary when writing a printf-type function. Any parameters you require are easily unset from the array you retrieve with func_get_args():

<?php

function mysprintf($format) {
   
$args = func_get_args();
    unset(
$args[0]); /* get rid of "$format" */
   
return vsprintf($format, $args);
}

/* I use this technique in production code as follows: */
function logf($target, $string) {
   
$args = func_get_args();
    unset(
$args[0], $args[1]);
   
fprintf($GLOBALS['config']['logtargets'][$target],
       
"[%s] %s\n", date('H:i'), wordwrap(vsprintf($string, $args), 75, '\n\r '));
}

/* e.g.:
    logf(DEBUG, "Oops! %s", mysql_error());
 */

?>

array_shift() and other costly array operations aren't required, as far as I know. I could be wrong.

drm at melp dot nl (30-Jan-2004 05:02)

When combining with func_get_args as above, you might want to consider using array_shift:

<?
function someFunc () {
   $args = func_get_args ();
   $format = array_shift ( $args );
   // do something
   return vsprintf ( $format, $args );
}
?>

keeps it clean ;)

samviseNOSPAM at hobbitonNOSPAM dot it (02-Jul-2002 02:55)

i wrote a short function that make use of vsprintf. It is useful in first coding/debugging of php scripts, because it is called like a simple printf and it display in italic (you can change it of course ;-) ) every debug messages, making it easy to remove them when your code is ready.

here goes :

<?php
function printd() {
       
$debug_array=func_get_args();
       
$debug_numargs=func_num_args();
       
$debug_fmt=$debug_array[0];
        for (
$i = 0 ; $i < $debug_numargs ; $i++ )
               
$debug_array[$i] = $debug_array[$i+1];
       
$debug_text=vsprintf($debug_fmt, $debug_array);
       
printf("--> debug <i>%s</i>\n",
               
$debug_text);
}
?>