PHP 8.4.2 Released!

vsprintf

(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)

vsprintfReturn a formatted string

Опис

vsprintf(string $format, array $values): string

Operates as sprintf() but accepts an array of arguments, rather than a variable number of arguments.

Параметри

format

Рядок формату складається з нуля або більше директив: звичайних символів (крім %), які відображаються в результаті без змін, та специфікаторів перетворення, для кожного з яких задається свій параметр.

Специфікатор перетворення відповідає прототипу: %[argnum$][flags][width][.precision]specifier.

Номер параметра

Ціле число, слідом за ним — знак долара $. Вказує порядковий номер параметра для перетворення.

Прапорці
Позначення Опис
- Вирівнює по лівому краю в межах заданої ширини. Праве вирівнювання виконується автоматично.
+ Дописує до додатнього числа знак +. Знак мінуса до від'ємного числа дописується автоматично.
(пропуск) Доповнює результат пропусками. Також виконується автоматично.
0 Доповнює число нулями ліворуч. Разом зі специфікатором s доповнює число нулями також праворуч.
' (символ) Доповнює рядок символом (символ).

Ширина

Може бути цілим числом, що вказує найменшу кількість символів в значенні після перетворення, або знак *. Якщо використано знак *, то ширина вказується як додаткове ціле число, що передує значенню, відформатованому специфікатором.

Точність

Крапка ., за якою (необов'язково) слідує ціле число чи знак *, значення якого залежить від специфікатора:

  • Для специфікаторів e, E, f і F — це кількість знаків, що будуть надруковані після десяткового розділювача (початково: 6).
  • Для специфікаторів g, G, h і H — найбільша допустима кількість значущих цифр, що будуть надруковані.
  • Для специфікатора s — діє як точка відсікання, встановлюючи максимальну кількість символів у рядку.

Зауваження: Якщо крапку вказано без зазначення точності, тоді точністю вважатиметься 0. Якщо використано знак *, то точність вказується як додаткове ціле число, що передує значенню, відформатованому специфікатором.

Специфікатори
Назва Опис
% Буквальний знак відсотка. Ніяких параметрів не потрібно.
b Параметр розглядається як ціле число і відображається як двійкове число.
c Параметр розглядається як ціле число і відображається як символ з таким кодом ASCII.
d Параметр розглядається як ціле число і відображається як знакове десяткове число.
e Параметр розглядається як експоненційний запис (напр. 1.2e+2).
E Схожий до специфікатора e, але використовує знак експоненти з великої букви (напр. 1.2E+2).
f Параметр розглядається і відображається як десятковий дріб (з урахуванням локалі).
F Параметр розглядається і відображається як десятковий дріб (БЕЗ урахування локалі).
g

Загальний формат.

Нехай P дорівнює точності, якщо вона не дорівнює нулю, 6, якщо точність не вказано, або 1, якщо точність дорівнює нулю. Тоді, якщо перетворення в стилі "E" матиме показник степеня X:

Якщо P > X ≥ −4, перетворення буде в стилі "f" та з точністю P − (X + 1). Інакше, перетворення буде в стилі "e" та з точністю P − 1.

G Схожий до специфікатора g, але використовує E та f.
h Схожий до специфікатора g, але використовує F. Доступний, починаючи з PHP 8.0.0.
H Схожий до специфікатора g, але використовує E та F. Доступний, починаючи з PHP 8.0.0.
o Параметр розглядається як ціле число і відображається як вісімкове число.
s Параметр розглядається і відображається як рядок.
u Параметр розглядається як ціле число і відображається як беззнакове десяткове число.
x Параметр розглядається як ціле число і відображається як шіснадцяткове число (з малими буквами).
X Параметр розглядається як ціле число і відображається як шіснадцяткове число (з великими буквами).

Увага

Специфікатор "c" ігнорує заповнення та ширину.

Увага

Спроба використати разом рядковий специфікатор та специфікатор ширини з символами, що займають більше одного байта, може призвести до неочікуваного результату.

Змінні будуть приведені до відповідного типу для специфікатора:

Обробка типів
Тип Специфікатор
string s
int d, u, c, o, x, X, b
float e, E, f, F, g, G, h, H

values

Значення, що повертаються

Return array values as a formatted string according to format.

Помилки/виключення

Починаючи з PHP 8.0.0, якщо не задано жодного параметра, то викидається ValueError. Раніше виводилось повідомлення E_WARNING.

Починаючи з PHP 8.0.0, якщо значення [width] менше за нуль або більше за PHP_INT_MAX, то викидається ValueError. Раніше виводилось повідомлення E_WARNING.

Починаючи з PHP 8.0.0, якщо значення [precision] менше за нуль або більше за PHP_INT_MAX, то викидається ValueError. Раніше виводилось повідомлення E_WARNING.

Починаючи з PHP 8.0.0, якщо якщо не задано обов'язкові параметри, то викидається ValueError. Раніше функція повертала false, а також виводилося повідомлення E_WARNING.

Журнал змін

Версія Опис
8.0.0 Ця функція більше не повертає false у разі помилки.
8.0.0 Викидає ValueError, якщо не задано жодного параметра. Раніше ця функція виводила E_WARNING.
8.0.0 Викидає ValueError, якщо значення [width] менше за нуль або більше за PHP_INT_MAX. Раніше ця функція виводила E_WARNING.
8.0.0 Викидає ValueError, якщо значення [precision] менше за нуль або більше за PHP_INT_MAX. Раніше ця функція виводила E_WARNING.
8.0.0 Викидає ValueError, якщо не задано обов'язкові параметри. Раніше ця функція виводила E_WARNING.

Приклади

Приклад #1 vsprintf(): zero-padded integers

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

Поданий вище приклад виведе:

1988-08-01

Прогляньте також

  • printf() - Output a formatted string
  • sprintf() - Return a formatted string
  • fprintf() - Write a formatted string to a stream
  • vprintf() - Output a formatted string
  • vfprintf() - Write a formatted string to a stream
  • sscanf() - Parses input from a string according to a format
  • fscanf() - Parses input from a file according to a format
  • number_format() - Format a number with grouped thousands
  • date() - Format a Unix timestamp

add a note

User Contributed Notes 10 notes

up
46
spectrumcat
8 years ago
Instead of inventing own functions in case you'd like to use array keys as placeholder names and replace corresponding array values in a string, just use the str_replace:

$string = 'Hello %name!';
$data = array(
'%name' => 'John'
);

$greeting = str_replace(array_keys($data), array_values($data), $string);
up
13
Josef Kufner
12 years ago
<?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);
}
?>
up
4
crash
3 years ago
Note that this function now throws an ValueError* as of PHP 8.0 if there is an error:

$ php -r 'var_dump(vsprintf("%d", []));'
> Fatal error: Uncaught ValueError: The arguments array must contain 1 items, 0 given in Command line code:1

*ValueError is new in PHP 8.0, so if you want to make your code compatible to PHP 7.x you should test that the arguments array has the correct length.
up
1
steven at nevvix dot com
6 years ago
<?php
/**
* Return a formatted string like vsprintf() with named placeholders.
*
* When a placeholder doesn't have a matching key in `$args`,
* the placeholder is returned as is to see missing args.
* @param string $format
* @param array $args
* @param string $pattern
* @return string
*/
function p($format, array $args, $pattern="/\{(\w+)\}/") {
return
preg_replace_callback($pattern, function ($matches) use ($args) {
return @
$args[$matches[1]] ?: $matches[0];
},
$format);
}

$args = ["database"=>"people", "user"=>"staff", "pass"=>"pass123", "host"=>"localhost"];

// With PHP-like placeholders: the variable is embedded in a string "{$database}" but without the dollar sign
$format = <<<SQL
CREATE DATABASE IF NOT EXISTS {database};
GRANT ALL PRIVILEGES ON {database_name}.* TO '{user}'@'{host}';
SET PASSWORD = PASSWORD('{pass}');
SQL;
echo
p($format, $args);
/*
Result:

CREATE DATABASE IF NOT EXISTS people;
GRANT ALL PRIVILEGES ON {database_name}.* TO 'staff'@'localhost';
SET PASSWORD = PASSWORD('pass123');

The `{database_name}` placeholder doesn't exist as a matching key in `$args` so it's returned as is.
*/

// With Ruby-like placeholders
$format = <<<SQL
CREATE DATABASE IF NOT EXISTS :database;
GRANT ALL PRIVILEGES ON :database_name.* TO ':user'@':host';
SET PASSWORD = PASSWORD(':pass');
SQL;
echo
p($format, $args, "/:(\w+)/");
/*
Result:

CREATE DATABASE IF NOT EXISTS people;
GRANT ALL PRIVILEGES ON :database_name.* TO 'staff'@'localhost';
SET PASSWORD = PASSWORD('pass123');

The `:database_name` placeholder doesn't exist as a matching key in `$args` so it's returned as is.
*/
up
4
jon at ardentcreative dot co dot uk
18 years ago
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>';
}
}
?>
up
4
Roadster
18 years ago
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.
up
3
www dot wesley at gmail dot com
16 years ago
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"
?>
up
2
dee jay simple zero07 at geemail dawt co
11 years ago
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;
?>
up
1
jed at NOSPAM dot jed dot bz
20 years ago
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.
up
1
ASchmidt at Anamera dot net
7 years ago
It's necessary to clearly how to apply argument swapping when using an array of arguments. One might be tempted to use %0$ to reference $args[0].

In reality, the position specifier is always the array index+1:

$args[0] is referenced by %1$...
$args[1] is referenced by %2$...
etc.

Similarly, the first subpattern of a RegEx match would be found in $matches[1], the second in $match[2], etc. However if the $matches array is used as arguments to vsprint(), then the position specifier is subpattern+1:

preg_match( $pattern, $subject, $matches );
vsprintf( 'Full Match = %1$s, first Subpattern = %2$s, second Subpattern = %3$s', $matches );
To Top