PHP 8.4.1 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
43
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
5
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
14
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
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
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
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
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