PHP Conference Nagoya 2025

vsprintf

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

vsprintfRetorna uma string formatada

Descrição

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

Funciona como sprintf() mas aceita um array de argumentos, ao invés de um número variável de argumentos.

Parâmetros

format

A string de formato é composta de zero ou mais diretivas: caracteres comuns (excluindo %) que são copiados diretamente para o resultado e especificações de conversão, cada uma das quais resulta na busca de seu próprio parâmetro.

Uma especificação de conversão segue este protótipo: %[argnum$][flags][width][.precision]especificador.

Argnum

Um número inteiro seguido por um cifrão $, para especificar qual o número de argumento a tratar na conversão.

Flags
Flag Descrição
- Justificar à esquerda dentro da largura de campo especificada; A justificação à direita é o padrão.
+ Prefixa números positivos com um sinal de mais +; Por padrão, apenas números negativos são prefixados com um sinal negativo.
(espaço) Preenche o resultado com espaços. Este é o padrão.
0 Preenche números com zeros apenas à esquerda. Com os especificadores s, também pode preencher com zeros à direita.
'(char) Preenche o resultado com o caractere (char).

Width

Um número inteiro que define em quantos caracteres (mínimo) esta conversão deve resultar, ou *. Se * for usado, a largura será fornecida como um valor inteiro adicional precedendo aquele formatado pelo especificador.

Precision

Um ponto . opcionalmente seguido por um número inteiro ou *, cujo significado depende do especificador:

  • Para os especificadores e, E, f e F: este é o número de dígitos a serem impressos após o ponto decimal (por padrão, é 6).
  • Para os especificadores g, G, h e H: este é o número máximo de dígitos significativos a serem impressos.
  • Para o especificador s: atua como um ponto de corte, definindo um limite máximo de caracteres para a string.

Nota: Se o ponto for especificado sem um valor explícito para precisão, 0 é assumido. Se * for usado, a precisão é fornecida como um valor inteiro adicional precedendo aquele formatado pelo especificador.

Especificadores
Especificador Descrição
% Um caractere literal de porcentagem. Nenhum argumento é necessário.
b O argumento é tratado como um número inteiro e apresentado como um número binário.
c O argumento é tratado como um número inteiro e apresentado como o caractere com aquele código ASCII.
d O argumento é tratado como um número inteiro e apresentado como um número decimal (com sinal).
e O argumento é tratado como notação científica (por exemplo, 1.2e+2).
E Como o especificador e, mas usa letra maiúscula (por exemplo, 1.2E+2).
f O argumento é tratado como um float e apresentado como um número de ponto flutuante (com reconhecimento da localidade).
F O argumento é tratado como um float e apresentado como um número de ponto flutuante (sem reconhecimento da localidade).
g

Formato geral.

Deixa P igual à precisão se for diferente de zero, 6 se a precisão for omitida, ou 1 se a precisão for zero. Então, se uma conversão com estilo E tivesse um expoente de X:

Se P > X ≥ −4, a conversão é com estilo f e precisão P − (X + 1). Caso contrário, a conversão é com estilo e e precisão P − 1.

G Como o especificador g, mas usa E e f.
h Como o especificador g, mas usa F. Disponível a partir do PHP 8.0.0.
H Como o especificador g, mas usa E e F. Disponível a partir do PHP 8.0.0.
o O argumento é tratado como um número inteiro e apresentado como um número octal.
s O argumento é tratado e apresentado como uma string.
u O argumento é tratado como um número inteiro e apresentado como um número decimal sem sinal.
x O argumento é tratado como um número inteiro e apresentado como um número hexadecimal (com letras minúsculas).
X O argumento é tratado como um número inteiro e apresentado como um número hexadecimal (com letras maiúsculas).

Aviso

O especificador de tipo c ignora preenchimento e largura.

Aviso

Tentar usar uma combinação dos especificadores de string e largura com conjuntos de caracteres que requerem mais de um byte por caractere pode resultar em resultados inesperados.

As variáveis serão forçadas a um tipo adequado para o especificador:

Tratamento de Tipos
Tipo Especificadores
string s
int d, u, c, o, x, X, b
float e, E, f, F, g, G, h, H

values

Valor Retornado

Retorna valores de array como uma string formatada de acordo com format.

Erros/Exceções

A partir do PHP 8.0.0, um erro ValueError será lançado se o número de argumentos for zero. Antes do PHP 8.0.0, um E_WARNING era emitido.

A partir do PHP 8.0.0, um erro ValueError será lançado se [width] for menor que zero ou maior que PHP_INT_MAX. Antes do PHP 8.0.0, um E_WARNING era emitido.

A partir do PHP 8.0.0, um erro ValueError será lançado se [precision] for menor que zero ou maior que PHP_INT_MAX. Antes do PHP 8.0.0, um E_WARNING era emitido.

A partir do PHP 8.0.0, um erro ArgumentCountError será lançado quando menos argumentos do que o necessário forem fornecidos. Antes do PHP 8.0.0, false era retornado e um E_WARNING era emitido.

Registro de Alterações

Versão Descrição
8.0.0 Esta função não mais retorna false em caso de falha.
8.0.0 Lança uma exceção ValueError se o número de argumentos for zero; anteriormente esta função emitia um E_WARNING.
8.0.0 Lança uma exceção ValueError se [width] for menor que zero ou maior que PHP_INT_MAX; anteriormente esta função emitia um E_WARNING.
8.0.0 Lança uma exceção ValueError se [precision] for menor que zero ou maior que PHP_INT_MAX; anteriormente esta função emitia um E_WARNING.
8.0.0 Lança uma exceção ValueError quando houver menos parâmetros que os necessários; anteriormente esta função emitia um E_WARNING.

Exemplos

Exemplo #1 vsprintf(): inteiros preenchidos com zero

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

O exemplo acima produzirá:

1988-08-01

Veja Também

  • printf() - Envia uma string formatada para a saída
  • sprintf() - Retona uma string formatada
  • fprintf() - Escreve uma string formatada para um fluxo
  • vprintf() - Mostra uma string formatada
  • vfprintf() - Escreve uma string formatada para um fluxo
  • sscanf() - Interpreta a entrada de uma string de acordo com um formato
  • fscanf() - Interpreta a leitura de um arquivo de acordo com um formato
  • number_format() - Formata um número com milhares agrupados
  • date() - Formata um timestamp Unix

adicione uma nota

Notas Enviadas por Usuários (em inglês) 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