返回一个由 C 库函数 sprintf
的常用 printf
约定格式化的字符串。有关更多详细信息,请参见下文,并参见系统上的 sprintf(3) 或 printf(3) 以了解一般原理。
例如
# Format number with up to 8 leading zeroes
my $result = sprintf("%08d", $number);
# Round number to 3 digits after decimal point
my $rounded = sprintf("%.3f", $number);
Perl 执行自己的 sprintf
格式化:它模拟 C 函数 sprintf(3),但除了浮点数以外不使用它,即使在使用时,也只允许标准修饰符。因此,您本地 sprintf(3) 中的非标准扩展在 Perl 中不可用。
与 printf
不同,当您将数组作为第一个参数传递给 sprintf
时,它不会执行您可能想要的操作。数组将被赋予标量上下文,并且 Perl 将使用数组中元素的计数作为格式,而不是使用数组的第 0 个元素作为格式,这几乎没有用处。
Perl 的 sprintf
允许以下普遍已知的转换
%% a percent sign
%c a character with the given number
%s a string
%d a signed integer, in decimal
%u an unsigned integer, in decimal
%o an unsigned integer, in octal
%x an unsigned integer, in hexadecimal
%e a floating-point number, in scientific notation
%f a floating-point number, in fixed decimal notation
%g a floating-point number, in %e or %f notation
此外,Perl 允许以下广泛支持的转换
%X like %x, but using upper-case letters
%E like %e, but using an upper-case "E"
%G like %g, but with an upper-case "E" (if applicable)
%b an unsigned integer, in binary
%B like %b, but using an upper-case "B" with the # flag
%p a pointer (outputs the Perl value's address in hexadecimal)
%n special: *stores* the number of characters output so far
into the next argument in the parameter list
%a hexadecimal floating point
%A like %a, but using upper-case letters
最后,为了向后(我们确实指的是“向后”)兼容性,Perl 允许这些不必要的但被广泛支持的转换
%i a synonym for %d
%D a synonym for %ld
%U a synonym for %lu
%O a synonym for %lo
%F a synonym for %f
请注意,%e
、%E
、%g
和 %G
生成的科学记数法中指数位数的数量,对于指数模数小于 100 的数字,是系统相关的:它可能是三个或更少(根据需要用零填充)。换句话说,1.23 乘以 10 的 99 次方可能是“1.23e99”或“1.23e099”。类似地,对于 %a
和 %A
:指数或十六进制数字可能会浮动:特别是“长双精度”Perl 配置选项可能会导致意外情况。
在 %
和格式字母之间,您可以指定几个额外的属性来控制格式的解释。按顺序,这些是
一个显式的格式参数索引,例如 2$
。默认情况下,sprintf 将格式化列表中下一个未使用的参数,但这允许您按顺序获取参数
printf '%2$d %1$d', 12, 34; # prints "34 12"
printf '%3$d %d %1$d', 1, 2, 3; # prints "3 1 1"
一个或多个
space prefix non-negative number with a space
+ prefix non-negative number with a plus sign
- left-justify within the field
0 use zeros, not spaces, to right-justify
# ensure the leading "0" for any octal,
prefix non-zero hexadecimal with "0x" or "0X",
prefix non-zero binary with "0b" or "0B"
例如
printf '<% d>', 12; # prints "< 12>"
printf '<% d>', 0; # prints "< 0>"
printf '<% d>', -12; # prints "<-12>"
printf '<%+d>', 12; # prints "<+12>"
printf '<%+d>', 0; # prints "<+0>"
printf '<%+d>', -12; # prints "<-12>"
printf '<%6s>', 12; # prints "< 12>"
printf '<%-6s>', 12; # prints "<12 >"
printf '<%06s>', 12; # prints "<000012>"
printf '<%#o>', 12; # prints "<014>"
printf '<%#x>', 12; # prints "<0xc>"
printf '<%#X>', 12; # prints "<0XC>"
printf '<%#b>', 12; # prints "<0b1100>"
printf '<%#B>', 12; # prints "<0B1100>"
当空格和加号作为标志同时给出时,空格将被忽略。
printf '<%+ d>', 12; # prints "<+12>"
printf '<% +d>', 12; # prints "<+12>"
当 # 标志和精度在 %o 转换中给出时,如果需要前导“0”,则精度将增加。
printf '<%#.5o>', 012; # prints "<00012>"
printf '<%#.5o>', 012345; # prints "<012345>"
printf '<%#.0o>', 0; # prints "<0>"
此标志告诉 Perl 将提供的字符串解释为整数向量,每个字符对应一个整数。Perl 依次将格式应用于每个整数,然后使用分隔符(默认情况下为点 .
)连接生成的字符串。这对于显示任意字符串中字符的序数值很有用
printf "%vd", "AB\x{100}"; # prints "65.66.256"
printf "version is v%vd\n", $^V; # Perl's version
在 v
之前放置一个星号 *
以覆盖用于分隔数字的字符串
printf "address is %*vX\n", ":", $addr; # IPv6 address
printf "bits are %0*v8b\n", " ", $bits; # random bitstring
您还可以使用类似 *2$v
的内容显式指定用于连接字符串的参数编号;例如
printf '%*4$vX %*4$vX %*4$vX', # 3 IPv6 addresses
@addr[1..3], ":";
参数通常格式化为仅显示给定值所需的宽度。您可以通过在此处放置一个数字来覆盖宽度,或者从下一个参数(使用 *
)或从指定参数(例如,使用 *2$
)获取宽度
printf "<%s>", "a"; # prints "<a>"
printf "<%6s>", "a"; # prints "< a>"
printf "<%*s>", 6, "a"; # prints "< a>"
printf '<%*2$s>', "a", 6; # prints "< a>"
printf "<%2s>", "long"; # prints "<long>" (does not truncate)
如果通过 *
获得的字段宽度为负数,则它与 -
标志具有相同的效果:左对齐。
您可以通过指定一个 .
后面跟着一个数字来指定精度(用于数字转换)或最大宽度(用于字符串转换)。对于除 g
和 G
之外的浮点格式,这指定了小数点右侧显示多少位(默认值为 6)。例如
# these examples are subject to system-specific variation
printf '<%f>', 1; # prints "<1.000000>"
printf '<%.1f>', 1; # prints "<1.0>"
printf '<%.0f>', 1; # prints "<1>"
printf '<%e>', 10; # prints "<1.000000e+01>"
printf '<%.1e>', 10; # prints "<1.0e+01>"
对于 "g" 和 "G",这指定了要显示的最大有效数字位数;例如
# These examples are subject to system-specific variation.
printf '<%g>', 1; # prints "<1>"
printf '<%.10g>', 1; # prints "<1>"
printf '<%g>', 100; # prints "<100>"
printf '<%.1g>', 100; # prints "<1e+02>"
printf '<%.2g>', 100.01; # prints "<1e+02>"
printf '<%.5g>', 100.01; # prints "<100.01>"
printf '<%.4g>', 100.01; # prints "<100>"
printf '<%.1g>', 0.0111; # prints "<0.01>"
printf '<%.2g>', 0.0111; # prints "<0.011>"
printf '<%.3g>', 0.0111; # prints "<0.0111>"
对于整数转换,指定精度意味着数字本身的输出应使用此宽度进行零填充,其中 0 标志被忽略
printf '<%.6d>', 1; # prints "<000001>"
printf '<%+.6d>', 1; # prints "<+000001>"
printf '<%-10.6d>', 1; # prints "<000001 >"
printf '<%10.6d>', 1; # prints "< 000001>"
printf '<%010.6d>', 1; # prints "< 000001>"
printf '<%+10.6d>', 1; # prints "< +000001>"
printf '<%.6x>', 1; # prints "<000001>"
printf '<%#.6x>', 1; # prints "<0x000001>"
printf '<%-10.6x>', 1; # prints "<000001 >"
printf '<%10.6x>', 1; # prints "< 000001>"
printf '<%010.6x>', 1; # prints "< 000001>"
printf '<%#10.6x>', 1; # prints "< 0x000001>"
对于字符串转换,指定精度会截断字符串以适合指定的宽度
printf '<%.5s>', "truncated"; # prints "<trunc>"
printf '<%10.5s>', "truncated"; # prints "< trunc>"
您还可以使用 .*
从下一个参数获取精度,或从指定的参数获取精度(例如,使用 .*2$
)
printf '<%.6x>', 1; # prints "<000001>"
printf '<%.*x>', 6, 1; # prints "<000001>"
printf '<%.*2$x>', 1, 6; # prints "<000001>"
printf '<%6.*2$x>', 1, 4; # prints "< 0001>"
如果通过 *
获得的精度为负数,则它被视为没有精度。
printf '<%.*s>', 7, "string"; # prints "<string>"
printf '<%.*s>', 3, "string"; # prints "<str>"
printf '<%.*s>', 0, "string"; # prints "<>"
printf '<%.*s>', -1, "string"; # prints "<string>"
printf '<%.*d>', 1, 0; # prints "<0>"
printf '<%.*d>', 0, 0; # prints "<>"
printf '<%.*d>', -1, 0; # prints "<0>"
对于数字转换,您可以使用 l
、h
、V
、q
、L
或 ll
指定解释数字的大小。对于整数转换(d u o x X b i D U O
),数字通常被假定为平台上的默认整数大小(通常为 32 或 64 位),但您可以覆盖它以改为使用标准 C 类型之一,如用于构建 Perl 的编译器所支持的
hh interpret integer as C type "char" or "unsigned
char" on Perl 5.14 or later
h interpret integer as C type "short" or
"unsigned short"
j interpret integer as C type "intmax_t" on Perl
5.14 or later; and prior to Perl 5.30, only with
a C99 compiler (unportable)
l interpret integer as C type "long" or
"unsigned long"
q, L, or ll interpret integer as C type "long long",
"unsigned long long", or "quad" (typically
64-bit integers)
t interpret integer as C type "ptrdiff_t" on Perl
5.14 or later
z interpret integer as C types "size_t" or
"ssize_t" on Perl 5.14 or later
请注意,通常情况下,在 Perl 代码中使用 l
修饰符(例如,在编写 "%ld"
或 "%lu"
而不是 "%d"
和 "%u"
时)是不必要的。此外,它可能是有害的,例如在 Windows 64 位系统上,long 是 32 位。
从 5.14 开始,如果它们在您的平台上不受支持,这些都不会引发异常。但是,如果启用了警告,则会发出 printf
警告类别的警告,以指示不支持的转换标志。如果您希望改为引发异常,请执行以下操作
use warnings FATAL => "printf";
如果您想在开始运行程序之前了解版本依赖关系,请在程序顶部添加类似以下内容
use v5.14; # for hh/j/t/z/ printf modifiers
您可以通过 Config 了解您的 Perl 是否支持四元组
use Config;
if ($Config{use64bitint} eq "define"
|| $Config{longsize} >= 8) {
print "Nice quads!\n";
}
对于浮点转换(e f g E F G
),数字通常被假定为平台上的默认浮点大小(双精度或长双精度),但如果您平台支持,您可以使用 q
、L
或 ll
强制使用 "长双精度"。您可以通过 Config 了解您的 Perl 是否支持长双精度
use Config;
print "long doubles\n" if $Config{d_longdbl} eq "define";
您可以通过 Config 了解 Perl 是否将 "长双精度" 视为平台上要使用的默认浮点大小
use Config;
if ($Config{uselongdouble} eq "define") {
print "long doubles by default\n";
}
长双精度和双精度也可能是一样的
use Config;
($Config{doublesize} == $Config{longdblsize}) &&
print "doubles are long doubles\n";
大小说明符V
对 Perl 代码没有影响,但为了与 XS 代码兼容而支持。它表示“使用 Perl 整数或浮点数的标准大小”,这是默认值。
通常,sprintf
将下一个未使用的参数作为每个格式说明的格式化值。如果格式说明使用*
来要求额外的参数,这些参数将按照它们在格式说明中出现的顺序从参数列表中消耗,在格式化值之前。当参数由显式索引指定时,这不会影响参数的正常顺序,即使显式指定的索引将是下一个参数。
所以
printf "<%*.*s>", $a, $b, $c;
使用$a
作为宽度,$b
作为精度,$c
作为格式化值;而
printf '<%*1$.*s>', $a, $b;
将使用$a
作为宽度和精度,$b
作为格式化值。
以下是一些更多示例;请注意,在使用显式索引时,可能需要转义$
printf "%2\$d %d\n", 12, 34; # will print "34 12\n"
printf "%2\$d %d %d\n", 12, 34; # will print "34 12 34\n"
printf "%3\$d %d %d\n", 12, 34, 56; # will print "56 12 34\n"
printf "%2\$*3\$d %d\n", 12, 34, 3; # will print " 34 12\n"
printf "%*1\$.*f\n", 4, 5, 10; # will print "5.0000\n"
如果use locale
(包括use locale ':not_characters'
)生效,并且POSIX::setlocale
已被调用,则格式化浮点数中使用的十进制分隔符将受LC_NUMERIC
区域设置的影响。参见perllocale和POSIX。