sprintf FORMAT, LIST

傳回一個字串,其格式化方式遵循 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),但除了浮點數以外,不會使用它,而且即使如此,也只允許使用標準修改器。因此,Perl 無法使用您所在 sprintf(3) 中的非標準擴充功能。

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

請注意,對於指數模數小於 100 的數字,%e%E%g%G 產生的科學記號中指數數字的數量取決於系統:它可能是三個或更少(視需要以零填充)。換句話說,1.23 乘以 10 的 99 次方可能是「1.23e99」或「1.23e099」。%a%A 也類似:指數或十六進位數字可能會浮動:特別是 Perl 組態選項「long doubles」可能會造成驚喜。

% 和格式字母之間,您可以指定幾個額外的屬性來控制格式的詮釋。依序為

格式參數索引

明確的格式參數索引,例如 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)

如果透過 * 取得的欄位寬度為負值,則其效果與 - 旗標相同:靠左對齊。

精度,或最大寬度

您可以透過指定一個點 . 後接一個數字來指定精度(對於數字轉換)或最大寬度(對於字串轉換)。對於除了 gG 之外的浮點格式,這會指定小數點右邊要顯示幾個位數(預設為 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>"
大小

對於數字轉換,您可以使用 lhVqLll 指定要將數字解譯為的大小。對於整數轉換(d u o x X b i D U O),數字通常假設為您的平台上的預設整數大小(通常為 32 或 64 位元),但您可以覆寫此設定,改用編譯 Perl 所使用的編譯器支援的標準 C 類型之一

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 位元中,長度為 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),數字通常假設為您的平台上的預設浮點大小(雙精度或長雙精度),但如果您平台支援,您可以使用 qLll 強制使用「長雙精度」。您可以透過 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 區域設定的影響。請參閱 perllocalePOSIX