(PHP 4 >= 4.1.0, PHP 5)
vsprintf — 返回格式化字符串
根据 format
( sprintf() 函数文档中有相关描述)参数指定的格式,在一个字符串中返回一系列值。
Example #1 vsprintf(): 前导 0 的整数
<?php
print vsprintf("%04d-%02d-%02d", explode('-', '1988-8-1')); // 1988-08-01
?>
dee jay simple zero07 at geemail dawt co (2013-01-17 17:03:19)
Using a heredoc with vprintf:
<?php
$string = <<<THESTRING
I like the state of %1\$s <br />
I picked: %2\$d as a number, <br />
I also picked %2\$d as a number again <br />
%3\$s<br />
THESTRING;
$returnText = vprintf( $string, array('Oregon','7','I Love Oregon') );
echo $returnText;
?>
Josef Kufner (2012-11-20 23:51:39)
<?php
/**
* Like vsprintf, but accepts $args keys instead of order index.
* Both numeric and strings matching /[a-zA-Z0-9_-]+/ are allowed.
*
* Example: vskprintf('y = %y$d, x = %x$1.1f', array('x' => 1, 'y' => 2))
* Result: 'y = 2, x = 1.0'
*
* $args also can be object, then it's properties are retrieved
* using get_object_vars().
*
* '%s' without argument name works fine too. Everything vsprintf() can do
* is supported.
*
* @author Josef Kufner <jkufner(at)gmail.com>
*/
function vksprintf($str, $args)
{
if (is_object($args)) {
$args = get_object_vars($args);
}
$map = array_flip(array_keys($args));
$new_str = preg_replace_callback('/(^|[^%])%([a-zA-Z0-9_-]+)\$/',
function($m) use ($map) { return $m[1].'%'.($map[$m[2]] + 1).'$'; },
$str);
return vsprintf($new_str, $args);
}
?>
thomas att familie dash flori dot de (2012-10-30 23:46:59)
Here is my example for named placeholders. It uses python like named placeholders except that it only allows /[a-z][a-zA-Z0-9_]/ for names.
<?php
/**
* Returns a formatted string. Accepts named arguments.
* @param string $format
* @param array $args
* @return string
**/
function vsprintfn($format, $args) {
// search format patterns
preg_match_all('/((?:^|[^%])(?:%%)*)%(\([a-z][a-zA-Z0-9_]*\))?((\+|-)?(0| |\'.)?-?[0-9\.]*[bcdeEufFgGosxX])/', $format, $matches);
// determine the order of the arguments
$j = 0;
$order = array();
foreach ($matches[0] as $i => $match) {
if ($matches[2][$i] == '') {
$key = $j++;
} else {
$key = substr($matches[2][$i],1,-1);
}
$order[] = $key;
}
// prepare the data array for vsprintf in the given order
$data = array();
foreach ($order as $key) {
if (isset($args[$key])) {
$data[] = $args[$key];
}
}
// replace named format patterns with default format patterns
$format = preg_replace('/((?:^|[^%])(?:%%)*)%(\([a-z][a-zA-Z0-9_]*\))((\+|-)?(0| |\'.)?-?[0-9\.]*[bcdeEufFgGosxX])/', '$1%$3', $format);
// return formatted string
return vsprintf($format, $data);
}
$exampleData = array(0=>2.2314123123,'test'=>2.1234883);
echo vsprintfn('%%2.5f = %2.5f', $exampleData) . "\n";
echo vsprintfn('%%(test)09.5f = %(test)\'%9.5f', $exampleData) . "\n";
?>
strata_ranger at hotmail dot com (2010-06-29 11:15:16)
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 (2009-03-04 04:52:45)
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 (2008-11-15 12:02: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 (2008-07-14 01:45:20)
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 (2008-06-16 13:56:17)
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 (2006-11-19 10:29:15)
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 (2006-09-30 19:44:52)
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 (2006-02-17 03:56:15)
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 (2005-12-19 09:27:45)
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 (2005-03-01 11:49:32)
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 (2004-05-22 18:48:36)
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 (2004-01-29 21:02:51)
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 (2002-07-02 06:55:01)
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);
}
?>