sprintf

(PHP 4, PHP 5, PHP 7, PHP 8)

sprintf返回格式化的字符串

描述

sprintf(string $format, mixed ...$values): string

根据格式字符串 format 返回生成的字符串。

参数

format

格式字符串由零个或多个指令组成:直接复制到结果中的普通字符(不包括 %)和 *转换说明符*,每个转换说明符都将获取其自己的参数。

转换说明符遵循以下原型:%[argnum$][flags][width][.precision]specifier

Argnum

一个整数,后跟一个美元符号 $,用于指定在转换中要处理的第几个参数。

Flags
Flag 描述
- 在给定的字段宽度内左对齐;右对齐是默认值
+ 用加号 + 为正数加前缀;默认情况下,只有负数会加负号前缀。
(空格) 用空格填充结果。这是默认值。
0 仅用零填充数字。对于 s 说明符,这也可以用零填充右侧。
'(字符) 用字符 (char) 填充结果。

Width

一个整数,表示此转换应产生的最小字符数,或 *。如果使用 *,则宽度将作为额外的整数值提供,该整数值在格式说明符之前。

Precision

一个句点 .,后跟一个整数或 *,其含义取决于说明符

  • 对于 eEfF 说明符:这是要在小数点后打印的位数(默认情况下为 6)。
  • 对于 gGhH 说明符:这是要打印的有效位数的最大值。
  • 对于 s 说明符:它充当截止点,设置字符串的最大字符限制。

注意: 如果指定了句点但不提供精度值,则假定为 0。如果使用 *,则精度将作为额外的整数值提供,该整数值在格式说明符之前。

Specifiers
Specifier 描述
% 一个字面百分号字符。不需要参数。
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 说明符类似,但使用 Ef
h g 说明符类似,但使用 F。从 PHP 8.0.0 开始可用。
H g 说明符类似,但使用 EF。从 PHP 8.0.0 开始可用。
o 参数将被视为整数,并以八进制数形式呈现。
s 参数将被视为字符串,并以字符串形式呈现。
u 参数将被视为整数,并以无符号十进制数形式呈现。
x 参数将被视为整数,并以十六进制数形式呈现(使用小写字母)。
X 参数将被视为整数,并以十六进制数形式呈现(使用大写字母)。

警告

c 类型说明符忽略填充和宽度。

警告

尝试将字符串和宽度说明符组合使用,以及需要多个字节来表示一个字符的字符集,可能会导致意外的结果。

变量将被强制转换为适合说明符的类型

类型处理
类型 Specifiers
string s
int ducoxXb
float eEfFgGhH

values

返回值

根据格式字符串 format 返回生成的字符串。

错误/异常

从 PHP 8.0.0 开始,如果参数数量为零,则会抛出 ValueError。在 PHP 8.0.0 之前,会发出 E_WARNING

从 PHP 8.0.0 开始,如果 [width] 小于零或大于 PHP_INT_MAX,则会抛出 ValueError。在 PHP 8.0.0 之前,会发出 E_WARNING

从 PHP 8.0.0 开始,如果 [precision] 小于零或大于 PHP_INT_MAX,则会抛出 ValueError。在 PHP 8.0.0 之前,会发出 E_WARNING

从 PHP 8.0.0 开始,当提供的参数少于所需参数时,会抛出 ArgumentCountError。在 PHP 8.0.0 之前,会返回 false 并发出 E_WARNING

变更日志

版本 描述
8.0.0 此函数不再在失败时返回 false
8.0.0 如果参数数量为零,则抛出 ValueError;之前此函数会发出 E_WARNING
8.0.0 如果 [width] 小于零或大于 PHP_INT_MAX,则抛出 ValueError;之前此函数会发出 E_WARNING
8.0.0 如果 [precision] 小于零或大于 PHP_INT_MAX,则抛出 ValueError;之前此函数会发出 E_WARNING
8.0.0 当提供的参数少于所需参数时,抛出 ArgumentCountError;之前此函数会发出 E_WARNING

示例

示例 #1 参数交换

格式字符串支持参数编号/交换。

<?php
$num
= 5;
$location = 'tree';

$format = 'There are %d monkeys in the %s';
echo
sprintf($format, $num, $location);
?>

上面的示例将输出

There are 5 monkeys in the tree

但是想象一下,我们在一个单独的文件中创建一个格式字符串,通常是因为我们想将其国际化,我们将其改写为

<?php
$format
= 'The %s contains %d monkeys';
echo
sprintf($format, $num, $location);
?>

现在我们遇到了一个问题。格式字符串中占位符的顺序与代码中参数的顺序不匹配。我们希望保留代码不变,只需在格式字符串中指示占位符所引用的参数。我们将在格式字符串中这样写

<?php
$format
= 'The %2$s contains %1$d monkeys';
echo
sprintf($format, $num, $location);
?>

另外一个好处是,可以在不向代码中添加更多参数的情况下重复使用占位符。

<?php
$format
= 'The %2$s contains %1$d monkeys.
That\'s a nice %2$s full of %1$d monkeys.'
;
echo
sprintf($format, $num, $location);
?>

使用参数交换时,n$ *位置说明符* 必须紧跟在百分号 (%) 后面,在任何其他说明符之前,如下所示。

示例 #2 指定填充字符

<?php
echo sprintf("%'.9d\n", 123);
echo
sprintf("%'.09d\n", 123);
?>

上面的示例将输出

......123
000000123

示例 #3 位置说明符与其他说明符

<?php
$format
= 'The %2$s contains %1$04d monkeys';
echo
sprintf($format, $num, $location);
?>

上面的示例将输出

The tree contains 0005 monkeys

示例 #4 sprintf(): 零填充整数

<?php
$isodate
= sprintf("%04d-%02d-%02d", $year, $month, $day);
?>

示例 #5 sprintf(): 格式化货币

<?php
$money1
= 68.75;
$money2 = 54.35;
$money = $money1 + $money2;
echo
$money;
echo
"\n";
$formatted = sprintf("%01.2f", $money);
echo
$formatted;
?>

上面的示例将输出

123.1
123.10

示例 #6 sprintf(): 科学记数法

<?php
$number
= 362525200;

echo
sprintf("%.3e", $number);
?>

上面的示例将输出

3.625e+8

参见

添加笔记

用户贡献的笔记 37 笔记

remy dot damour at -please-no-spam-laposte dot net
15 年前
使用 printf() 和 sprintf() 函数时,转义字符不是反斜杠 '\',而是 '%'.

例如,要打印 '%' 字符,需要用它本身转义
<?php
printf
('%%%s%%', 'koko'); #output: '%koko%'
?>
Alex R. Gibbs
11 年前
1. 加号 ('+') 表示在正数之前放置 '+', 而减号 ('-') 表示左对齐。文档错误地指出它们是可互换的。它们会产生独特的结果,可以组合使用

<?php
echo sprintf ("|%+4d|%+4d|\n", 1, -1);
echo
sprintf ("|%-4d|%-4d|\n", 1, -1);
echo
sprintf ("|%+-4d|%+-4d|\n", 1, -1);
?>

输出

| +1| -1|
|1 |-1 |
|+1 |-1 |

2. 使用 '0' 填充不同于使用其他字符填充。零只会添加到数字的前面,在任何符号之后。其他字符将添加到符号之前或数字之后

<?php
echo sprintf ("|%04d|\n", -2);
echo
sprintf ("|%':4d|\n", -2);
echo
sprintf ("|%-':4d|\n", -2);

// 同时指定 "-" 和 "0" 会产生冲突,导致意想不到的结果:
echo sprintf ("|%-04d|\n", -2);

// 使用其他数字填充的行为与其他非零字符相同:
echo sprintf ("|%-'14d|\n", -2);
echo
sprintf ("|%-'04d|\n", -2);
?>

输出

|-002|
|::-2|
|-2::|
|-2 |
|-211|
|-2 |
timo dot frenay at gmail dot com
13 年前
以下是如何打印具有 16 位有效数字的浮点数,无论其大小如何

<?php
$result
= sprintf(sprintf('%%.%dF', max(15 - floor(log10($value)), 0)), $value);
?>

这比执行类似 sprintf('%.15F', $value) 的操作更可靠,因为后者可能会截断非常小的数字的有效数字,或者打印虚假数字(意味着超过浮点数可以可靠表示的数字)的有效数字。非常大的数字。
kontakt at myseosolution dot de
9 年前
已经有一些关于使用 sprintf 强制前导零的评论,但示例只包括整数。我需要浮点数的前导零,并且惊讶地发现它没有按预期工作。

例子
<?php
sprintf
('%02d', 1);
?>

这将导致 01。但是,尝试对具有精度的浮点数进行相同的操作不起作用

<?php
sprintf
('%02.2f', 1);
?>

产生 1.00。

这让我有点不知所措。要获得所需的结果,需要添加精度 (2) 和小数分隔符 "." 的长度 (1)。所以正确的模式应该是

<?php
sprintf
('%05.2f', 1);
?>

输出:01.00

请参阅 http://stackoverflow.com/a/28739819/413531 获取更详细的解释。
匿名
7 年前
尝试使用重复占位符重构较长的字符串时要小心,例如

sprintf("Hi %s. Your name is %s", $name, $name);

使用参数编号进行重构

sprintf("Hi %1$s. Your name is %1$s", $name);

这会在 **运行时** 导致错误,因为 `$s` 会被视为变量。如果没有 `$s` 用于替换,就会抛出通知。

解决办法是使用单引号来防止字符串中的变量替换

sprintf('Hi %1$s. Your name is %1$s', $name);

如果需要变量替换,则需要将字符串拆分以保持单引号

sprintf("Hi " . '%1$s' . ". Your {$variable} is " . '%1$s', $name);
viktor at textalk dot com
15 年前
更完整且可行的 mb_sprintf 和 mb_vsprintf 版本。它应该适用于任何“保留 ASCII”编码,例如 UTF-8 和所有 ISO-8859 字符集。它处理符号、填充、对齐、宽度和精度。参数交换不受支持。

<?php
if (!function_exists('mb_sprintf')) {
function
mb_sprintf($format) {
$argv = func_get_args() ;
array_shift($argv) ;
return
mb_vsprintf($format, $argv) ;
}
}
if (!
function_exists('mb_vsprintf')) {
/**
* 支持所有编码格式和参数的函数。
* 支持:符号、填充、对齐、宽度和精度。
* 不支持:参数交换。
*/
function mb_vsprintf($format, $argv, $encoding=null) {
if (
is_null($encoding))
$encoding = mb_internal_encoding();

// 在格式中使用 UTF-8,以便在 preg_split 中使用 u 标志
$format = mb_convert_encoding($format, 'UTF-8', $encoding);

$newformat = ""; // 在 UTF-8 中构建一个新的格式
$newargv = array(); // 未处理的参数,保持原始编码

while ($format !== "") {

// 将格式根据第一个 %-指令分割成两个部分:$pre 和 $post
// 我们也得到匹配的组
list ($pre, $sign, $filler, $align, $size, $precision, $type, $post) =
preg_split("!\%(\+?)('.|[0 ]|)(-?)([1-9][0-9]*|)(\.[1-9][0-9]*|)([%a-zA-Z])!u",
$format, 2, PREG_SPLIT_DELIM_CAPTURE) ;

$newformat .= mb_convert_encoding($pre, $encoding, 'UTF-8');

if (
$type == '') {
// 没有匹配。什么也不做。这是最后一次迭代。
}
elseif (
$type == '%') {
// 转义的 %
$newformat .= '%%';
}
elseif (
$type == 's') {
$arg = array_shift($argv);
$arg = mb_convert_encoding($arg, 'UTF-8', $encoding);
$padding_pre = '';
$padding_post = '';

// 截断 $arg
if ($precision !== '') {
$precision = intval(substr($precision,1));
if (
$precision > 0 && mb_strlen($arg,$encoding) > $precision)
$arg = mb_substr($precision,0,$precision,$encoding);
}

// 定义填充
if ($size > 0) {
$arglen = mb_strlen($arg, $encoding);
if (
$arglen < $size) {
if(
$filler==='')
$filler = ' ';
if (
$align == '-')
$padding_post = str_repeat($filler, $size - $arglen);
else
$padding_pre = str_repeat($filler, $size - $arglen);
}
}

// 转义 % 并传递给下游
$newformat .= $padding_pre . str_replace('%', '%%', $arg) . $padding_post;
}
else {
// 其他类型,传递给下游
$newformat .= "%$sign$filler$align$size$precision$type";
$newargv[] = array_shift($argv);
}
$format = strval($post);
}
// 将新的格式从 UTF-8 转换回原始编码
$newformat = mb_convert_encoding($newformat, $encoding, 'UTF-8');
return
vsprintf($newformat, $newargv);
}
}
?>
nate at frickenate dot com
14 年前
以下是一组功能完善且简洁的函数,允许使用命名参数代替数字参数。例如:使用 sprintf('%name$s', array('name' => 'Joe')); 代替 sprintf('%1$s', 'Joe');。我提供了两种不同的版本:第一个使用类似 php 的语法(例如:%name$s),而第二个使用 python 的语法(例如:%(name)s)。

<?php

/**
* sprintf 的版本,用于需要命名参数的情况(php 语法)
*
* 使用 sprintf:sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
*
* 使用 sprintfn:sprintfn('second: %second$s ; first: %first$s', array(
* 'first' => '1st',
* 'second'=> '2nd'
* ));
*
* @param string $format sprintf 格式字符串,可以包含任意数量的命名参数
* @param array $args 数组,包含 [ 'arg_name' => 'arg value', ... ] 的替换内容
* @return string|false sprintf 调用的结果,或布尔值 false 表示错误
*/
function sprintfn ($format, array $args = array()) {
// 命名参数及其对应 sprintf 数字参数值的映射
$arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

// 查找下一个命名参数。每次搜索都从前一次替换的末尾开始。
for ($pos = 0; preg_match('/(?<=%)([a-zA-Z_]\w*)(?=\$)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
$arg_pos = $match[0][1];
$arg_len = strlen($match[0][0]);
$arg_key = $match[1][0];

// 程序员没有为格式字符串中找到的命名参数提供值
if (! array_key_exists($arg_key, $arg_nums)) {
user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
return
false;
}

// 将命名参数替换为相应的数字参数
$format = substr_replace($format, $replace = $arg_nums[$arg_key], $arg_pos, $arg_len);
$pos = $arg_pos + strlen($replace); // 跳到替换的末尾,以便进行下一次迭代
}

return
vsprintf($format, array_values($args));
}

/**
* sprintf 的版本,用于需要命名参数的情况(python 语法)
*
* 使用 sprintf:sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
*
* 使用 sprintfn:sprintfn('second: %(second)s ; first: %(first)s', array(
* 'first' => '1st',
* 'second'=> '2nd'
* ));
*
* @param string $format sprintf 格式字符串,可以包含任意数量的命名参数
* @param array $args 数组,包含 [ 'arg_name' => 'arg value', ... ] 的替换内容
* @return string|false sprintf 调用的结果,或布尔值 false 表示错误
*/
function sprintfn ($format, array $args = array()) {
// 命名参数及其对应 sprintf 数字参数值的映射
$arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

// 查找下一个命名参数。每次搜索都从前一次替换的末尾开始。
for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
$arg_pos = $match[0][1];
$arg_len = strlen($match[0][0]);
$arg_key = $match[1][0];

// 程序员没有为格式字符串中找到的命名参数提供值
if (! array_key_exists($arg_key, $arg_nums)) {
user_error("sprintfn(): Missing argument '${arg_key}'", E_USER_WARNING);
return
false;
}

// 将命名参数替换为相应的数字参数
$format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
$pos = $arg_pos + strlen($replace); // 跳到替换的末尾,以便进行下一次迭代
}

return
vsprintf($format, array_values($args));
}

?>
jfgrissom at gmail dot com
15 年前
我在尝试找到一个 32 位数字的二进制补码时做了一个噩梦。

我从 http://www.webmasterworld.com/forum88/13334.htm(应归功于其)获得此信息。

引用:...找出任何数字的 2 补码,即 -(pow(2, n) - N),其中 n 是位数,N 是要查找其 2 补码的数字。

这对我有奇效...之前我尝试使用

sprintf ("%b",$32BitDecimal);
但当 $32BitDecimal 值超过 2,000,000,000 时,它总是返回 10000000000000000000000。

这个 -(pow(2, n) - N)
效果非常好,而且非常准确。

希望这能帮助一些在 PHP 中与 2 补码作斗争的人。
ian dot w dot davis at gmail dot com
19 年前
为了详细说明 downright 关于 %f 不同含义的观点,它似乎从 4.3.7 版本开始发生了重大变化,而不仅仅是在不同平台上有所不同。以前,宽度说明符指定的是小数点前的字符数量。现在,宽度说明符指定的是总字符数量。(这与其他语言中 printf() 的语义一致。)请查看错误 #28633 和 #29286 以了解更多详细信息。
dwieeb at gmail dot com
13 年前
如果你使用默认的填充说明符(空格),然后将其打印到 HTML,你会注意到 HTML 不会正确显示多个空格。这是因为任何空白序列都被视为单个空格。

为了克服这个问题,我编写了一个简单的函数,它将 sprintf() 返回的字符串中的所有空格替换为字符实体引用 "&nbsp;",以便在 sprintf() 返回的字符串中实现不间断空格。

<?php
// 以下是函数:
function sprintf_nbsp() {
$args = func_get_args();
return
str_replace(' ', '&nbsp;', vsprintf(array_shift($args), array_values($args)));
}

// 用法(与 sprintf 完全一样):
$format = 'The %d monkeys are attacking the [%10s]!';
$str = sprintf_nbsp($format, 15, 'zoo');
echo
$str;
?>

上面的示例将输出
The 15 monkeys are attacking the [ zoo]!

<?php
// 打印字符串而不是返回字符串的变体:
function printf_nbsp() {
$args = func_get_args();
echo
str_replace(' ', '&nbsp;', vsprintf(array_shift($args), array_values($args)));
}
?>
php at mikeboers dot com
15 年前
继续讨论基于键的 sprintf 的主题...

我大致(我可以看到几个出现奇怪结果的案例)复制了 Python 使用字典进行字符串格式化的语法。与过去几次尝试相比,这一次的改进在于它仍然尊重所有格式选项,正如我的示例所示。

错误处理真的很糟糕(只是简单的 echo)。我只是把这个凑在一起,所以你可以随心所欲地使用它。=]

<?php

function sprintf_array($string, $array)
{
$keys = array_keys($array);
$keysmap = array_flip($keys);
$values = array_values($array);

while (
preg_match('/%\(([a-zA-Z0-9_ -]+)\)/', $string, $m))
{
if (!isset(
$keysmap[$m[1]]))
{
echo
"No key $m[1]\n";
return
false;
}

$string = str_replace($m[0], '%' . ($keysmap[$m[1]] + 1) . '$', $string);
}

array_unshift($values, $string);
var_dump($values);
return
call_user_func_array('sprintf', $values);
}

echo
sprintf_array('4 digit padded number: %(num)04d ', array('num' => 42));

?>

干杯!
krzysiek dot 333 at gmail dot com - zryty dot hekko dot pl
12 年前
将 IP 地址编码和解码为格式:1A2B3C4D(mysql 列:char(8))

<?php
function encode_ip($dotquad_ip)
{
$ip_sep = explode('.', $dotquad_ip);
return
sprintf('%02x%02x%02x%02x', $ip_sep[0], $ip_sep[1], $ip_sep[2], $ip_sep[3]);
}

function
decode_ip($int_ip)
{
$hexipbang = explode('.', chunk_split($int_ip, 2, '.'));
return
hexdec($hexipbang[0]). '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]);
}
?>
no dot email dot address at example dot com
21 年前
在 sprintf() 中使用 gettext 进行参数交换:假设你编写了以下脚本

<?php
$var
= sprintf(gettext("The %2\$s contains %1\$d monkeys"), 2, "cage");
?>

现在你运行 xgettext 来生成一个 .po 文件。.po 文件将看起来像这样

#: file.php:9
#, ycp-format
msgid "The %2\\$s contains %1\\$d monkeys"
msgstr ""

注意 xgettext 添加了一个额外的反斜杠。

翻译完字符串后,你必须从 ID 字符串和翻译中删除所有反斜杠,以便 po 文件看起来像这样

#: file.php:9
#, ycp-format
msgid "The %2$s contains %1$d monkeys"
msgstr "Der er %1$d aber i %2$s"

现在运行 msgfmt 生成 .mo 文件,如果需要,重新启动 Apache 以删除 gettext 缓存,然后你就完成了。
carmageddon at gmail dot com
13 年前
如果你想将十进制(整数)数字转换为固定长度的二进制数字,例如 9 位,请使用以下方法

$binary = sprintf('%08b', $number );

例如
<?php
$bin
= sprintf('%08b',511 );
echo
$bin."\n";
?>

将输出 111111111
而 2 将输出 00000010

我知道这些前导零对我来说很有用,也许对其他人也很有用。
Anderson
4 年前
那个帮助我很多的老“猴子”例子不幸消失了。

我将把它作为回忆在评论中重新发布。

<?php
$n
= 43951789;
$u = -43951789;
$c = 65; // ASCII 65 is 'A'

// notice the double %%, this prints a literal '%' character
printf("%%b = '%b'\n", $n); // binary representation
printf("%%c = '%c'\n", $c); // print the ascii character, same as chr() function
printf("%%d = '%d'\n", $n); // standard integer representation
printf("%%e = '%e'\n", $n); // scientific notation
printf("%%u = '%u'\n", $n); // unsigned integer representation of a positive integer
printf("%%u = '%u'\n", $u); // unsigned integer representation of a negative integer
printf("%%f = '%f'\n", $n); // floating point representation
printf("%%o = '%o'\n", $n); // octal representation
printf("%%s = '%s'\n", $n); // string representation
printf("%%x = '%x'\n", $n); // hexadecimal representation (lower-case)
printf("%%X = '%X'\n", $n); // hexadecimal representation (upper-case)

printf("%%+d = '%+d'\n", $n); // sign specifier on a positive integer
printf("%%+d = '%+d'\n", $u); // sign specifier on a negative integer

/*
%b = '10100111101010011010101101'
%c = 'A'
%d = '43951789'
%e = '4.395179e+7'
%u = '43951789'
%u = '18446744073665599827'
%f = '43951789.000000'
%o = '247523255'
%s = '43951789'
%x = '29ea6ad'
%X = '29EA6AD'
%+d = '+43951789'
%+d = '-43951789'
*/

$s = 'monkey';
$t = 'many monkeys';

printf("[%s]\n", $s); // standard string output
printf("[%10s]\n", $s); // right-justification with spaces
printf("[%-10s]\n", $s); // left-justification with spaces
printf("[%010s]\n", $s); // zero-padding works on strings too
printf("[%'#10s]\n", $s); // use the custom padding character '#'
printf("[%10.10s]\n", $t); // left-justification but with a cutoff of 10 characters

/*
[monkey]
[ monkey]
[monkey ]
[0000monkey]
[####monkey]
[many monke]
*/
?>
Pacogliss
19 年前
提醒初学者:示例 6 'printf("[%10s]\n", $s);' 只有在使用 html '<pre></pre>' 标签时才起作用(即显示空格)(节省头部刮取时间;-)。
john at jbwalker dot com
10 年前
我在上面的文档中找不到应该是一个警告的信息,那就是如果你的格式化字符串中的格式说明符比要匹配的变量多,sprintf 将什么都不返回。我认为,这一点也应该在返回值部分说明。
php at sharpdreams dot com
20 年前
请注意,在使用参数交换时,你必须对每个参数进行编号,否则 sprintf 会感到困惑。这种情况只发生在你先使用编号参数,然后切换到非编号参数,然后再切换回编号参数时。

<?php
$sql
= sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
// 不会运行:
// Sprintf 会抱怨参数不足。
$sql = sprintf( "select * from %1\$s left join %2\$s on( %1\$s.id = %2\$s.midpoint ) where %1\$s.name like '%%%3\$s%%' and %2\$s.tagname is not null", "table1", "table2", "bob" );
// 会运行:注意 %3\$s
?>
abiltcliffe at bigfoot.com
21 年前
对于 jrust at rustyparts.com,请注意,如果使用双引号字符串并且 *不* 使用反斜杠转义美元符号,则 $s 和 $d 将被解释为变量引用。反斜杠本身不属于格式说明符,但在编写格式字符串时需要包含它(除非使用单引号)。
Hayley Watson
12 年前
如果使用参数编号,则具有相同编号的格式规范将获得相同的参数;这可以节省在函数调用中重复参数。

<?php

$pattern
= '%1$s %1$\'#10s %1$s!';

printf($pattern, "badgers");
?>
geertdd at gmail dot com
13 年前
请注意,使用符号说明符时,数字零被视为正数,并且会为其添加一个“+”符号。

<?php
printf
('%+d', 0); // +0
?>
splogamurugan at gmail dot com
15 年前
$format = 'There are %1$d monkeys in the %s and %s ';
printf($format, 100, 'Chennai', 'Bangalore');

预期输出
"There are 100 monkeys in the Chennai and bangalore"

但,这将输出
"There are 100 monkeys in the 100 and Chennai"

因为,第二个和第三个说明符采用第一个和第二个参数。因为它没有分配任何参数。
jrpozo at conclase dot net
19 年前
如果您使用 %f 修饰符来舍入小数,请小心,因为它(从 4.3.10 开始)在设置某些语言环境时将不再生成浮点数,因此您无法累积结果。例如

setlocale(LC_ALL, 'es_ES');
echo(sprintf("%.2f", 13.332) + sprintf("%.2f", 14.446))

给出 27 而不是 27.78,因此请使用 %F 代替。
hdimac at gmail dot com
10 年前
在示例中,显示的是 printf,但应该说 sprintf,这是正在解释的函数……只是一个简单的编辑错误。
Astone
14 年前
当您使用 Google 翻译时,您必须通过在“转换规范”周围放置 <span class="notranslate"></span> 来“转义”它们。

像这样

<?php

function getGoogleTranslation($sString, $bEscapeParams = true)
{
// "转义" sprintf 参数
if ($bEscapeParams)
{
$sPatern = '/(?:%%|%(?:[0-9]+\$)?[+-]?(?:[ 0]|\'.)?-?[0-9]*(?:\.[0-9]+)?[bcdeufFosxX])/';
$sEscapeString = '<span class="notranslate">$0</span>';
$sString = preg_replace($sPatern, $sEscapeString, $sString);
}

// 组成数据数组(英语到荷兰语)
$aData = array(
'v' => '1.0',
'q' => $sString,
'langpair' => 'en|nl',
);

// 初始化连接
$rService = curl_init();

// 连接设置
curl_setopt($rService, CURLOPT_URL, 'http://ajax.googleapis.com/ajax/services/language/translate');
curl_setopt($rService, CURLOPT_RETURNTRANSFER, true);
curl_setopt($rService, CURLOPT_POSTFIELDS, $aData);

// 执行请求
$sResponse = curl_exec($rService);

// 关闭连接
curl_close($rService);

// 从 JSON 响应中提取文本
$oResponse = json_decode($sResponse);
if (isset(
$oResponse->responseData->translatedText))
{
$sTranslation = $oResponse->responseData->translatedText;
}
else
{
// 如果发生错误,则使用原始字符串
$sTranslation = $sString;
}

// 替换 "notranslate" 标签
if ($bEscapeParams)
{
$sEscapePatern = '/<span class="notranslate">([^<]*)<\/span>/';
$sTranslation = preg_replace($sEscapePatern, '$1', $sTranslation);
}

// 返回结果
return $sTranslation;
}

?>

感谢 MelTraX 定义了正则表达式!
ignat dot scheglovskiy at gmail dot com
11 年前
以下是如何使用对齐、填充和精度说明符打印格式化项目列表的示例

<?php

$out
= "The Books\n";
$books = array("Book 1", "Book 2", "Book 3");
$pages = array("123 pages ", "234 pages", "345 pages");
for (
$i = 0; $i < count($books); $i++) {
$out .= sprintf("%'.-20s%'.7.4s\n", $books[$i], $pages[$i]);
}
echo
$out;

// 输出:
//
// The Books
// Book 1.................123
// Book 2.................234
// Book 3.................345
?>
scott dot gardner at mac dot com
16 年前
在 Example#6 的最后一个示例中,关于输出存在错误。

printf("[%10.10s]\n", $t); // 左对齐,但截断为 10 个字符

这将输出右对齐。

为了输出左对齐

printf("[%-10.10s]\n", $t);
Anonymous
2 年前
如果格式字符串用双引号("")括起来,则需要在 argnum 后的美元符号前加上反斜杠字符(\),例如 %1\$s,这样 PHP 就不会尝试将它们解释为变量。使用反斜杠这样的操作称为转义序列。

<?php
// 示例字符串
$number = 499;
$format = "The number without decimal points: %1\$d, and the number with two decimal points: %1\$.2f";

// 格式化并打印字符串
printf($format, $number);
?>
iannacone
1 个月前
还值得注意的是,Argnum 从 1 开始,而不是 0。
nmmm at nmmm dot nu
9 年前
php printf 和 sprintf 似乎不支持星号“*”格式。

以下是一个示例

printf("%*d\n",3,5);

这将打印“d”而不是“<两个空格>5”
John Walker
15 年前
为了补充下面关于浮点数问题的其他说明,我注意到 %f 和 %F 显然将输出最大精度为 6 作为默认值,因此如果您需要更多精度,则必须指定 1.15f(例如)。

在我的情况下,输入(来自 MySQL)是一个具有 15 位精度的字符串,显示为 6 位。可能发生的情况是在转换为浮点数之前,在显示之前发生了舍入。将其显示为 1.15f(或在我的情况下为 %s)将显示正确的数字。
Andrew dot Wright at spamsux dot atnf dot csiro dot au
22 年前
我最后一个示例中的错误
$b = sprintf("%30.s", $a);
只会添加足够的空格到 $a 前面,以使空格 + strlen($a) 达到 30 个位置。

我在 72 个字符宽度的空间中居中固定文本的方法是

$a = "Some string here";
$lwidth = 36; // 72/2
$b = sprintf("%".($lwidth + round(strlen($a)/2)).".s", $a);
Sam Bull
8 年前
针对 sprintfn 函数的命名参数修复(https://php.net/manual/en/function.sprintf.php#94608

将第一行从
$arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);

$arg_nums = array_keys($args);
array_unshift($arg_nums, 0);
$arg_nums = array_flip(array_slice($arg_nums, 1, NULL, true));
ivan at php dot net
10 年前
viktor at textalk dot com 的 mb_vsprintf 函数代码中存在一个小问题。

在“截断 $arg”部分,以下行
$arg = mb_substr($precision,0,$precision,$encoding);
需要替换为
$arg = mb_substr($arg,0,$precision,$encoding);
Nathan Alan
7 年前
只想补充一点,要获取字符串中剩余的文本,你需要在你的 scanf 中添加以下内容作为变量

%[ -~]

例子

sscanf($sql, "[%d,%d]%[ -~]", $sheet_id, $column, $remaining_sql);
Mirek Z...
4 年前
我进行了一个简单的速度测试。将 sprintf 与 PHP 字符串连接运算符进行对比。测试在 PHP 7.3 上进行,共进行 100 万次迭代。

我运行了多次,发现字符串连接大约需要 2.9 秒,而 sprintf 则需要 4.3 秒。
我一直在思考哪种方法更快,当我们要格式化字符串(例如,向用户发送的消息或用于日志记录目的)时,包含一些变量值,哪种方法更好?是使用运算符(点“.”)连接字符串和变量,还是使用 sprintf?答案是:如果你不打算实现任何多语言机制,并且对硬编码一些文本感到满意,那么“点”运算符的速度几乎快 1.5 倍!

以下是代码

echo 'Start' . PHP_EOL;
$vS_text = 'some text';
$vS = '';
$vf = microtime(true);
for ($vI = 0; $vI < 1000000; $vI++) {
$vS = 'Start ' . $vI . ' ' . $vS_text . ' ' . $vf . ' end';
}
$vf = microtime(true) - $vf;
echo 'Concat:' . $vf . PHP_EOL;
$vS = '';
$vf = microtime(true);
for ($vI = 0; $vI < 1000000; $vI++) {
$vS = sprintf('Start %d %s %f end', $vI, $vS_text, $vf);
}
$vf = microtime(true) - $vf;
echo 'Spritf:' . $vf . PHP_EOL;
2838132019 at qq dot com
2 年前
echo sprintf("%.2f", "123456789012345.82");
// 结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.85");
// 结果:123456789012345.84

echo sprintf("%.2f", "123456789012345.87");
//结果:123456789012345.88

echo sprintf("%.2f", "123456789012345.820");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.821");
//结果:123456789012345.83

echo sprintf("%.2f", "123456789012345.828");
//结果:123456789012345.83

echo sprintf("%.2f", "123456789012345.8209");
//结果:123456789012345.83

echo sprintf("%.2f", "1234567890123456.82");
//结果:1234567890123456.75

echo sprintf("%.2f", "123456789012345.82002");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.820001");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.820101");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.820201");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.820301");
//结果:123456789012345.81

echo sprintf("%.2f", "123456789012345.820401");
//结果:123456789012345.83
To Top