格式规范

多个 Ruby 核心类具有实例方法 printfsprintf

这些方法中的每一个都接受

这些方法中的每一个都会打印或返回一个字符串,该字符串是将 format_string 中嵌入的每个格式规范替换为 arguments 中对应的参数的字符串形式的结果。

一个简单的例子

sprintf('Name: %s; value: %d', 'Foo', 0) # => "Name: Foo; value: 0"

格式规范的形式如下

%[flags][width][.precision]type

它由以下部分组成

除了前导百分号字符外,唯一必需的部分是类型指定符,因此我们从它开始。

类型指定符

本节简要解释每个类型指定符。这些链接会指向详细信息和示例。

整数类型指定符

浮点数类型指定符

其他类型指定符

标志

标志的效果在不同的类型指定符之间可能会有很大差异。这些备注本质上是通用的。请参阅特定于类型的详细信息

可以为单个类型指定符指定多个标志;顺序无关紧要。

' ' 标志

在非负数之前插入空格

sprintf('%d', 10)  # => "10"
sprintf('% d', 10) # => " 10"

为负值插入减号

sprintf('%d', -10)  # => "-10"
sprintf('% d', -10) # => "-10"

'#' 标志

使用备用格式;因类型而异

sprintf('%x', 100)  # => "64"
sprintf('%#x', 100) # => "0x64"

'+' 标志

为非负数添加前导加号

sprintf('%x', 100)  # => "64"
sprintf('%+x', 100) # => "+64"

'-' 标志

在其字段中左对齐值

sprintf('%6d', 100)  # => "   100"
sprintf('%-6d', 100) # => "100   "

'0' 标志

用零而不是空格进行左填充

sprintf('%6d', 100)  # => "   100"
sprintf('%06d', 100) # => "000100"

'*' 标志

使用下一个参数作为字段宽度

sprintf('%d', 20, 14)  # => "20"
sprintf('%*d', 20, 14) # => "                  14"

'n$' 标志

将(从 1 开始的)第 n 个参数格式化到此字段中

sprintf("%s %s", 'world', 'hello')     # => "world hello"
sprintf("%2$s %1$s", 'world', 'hello') # => "hello world"

宽度指定符

通常,宽度指定符确定格式化字段的最小宽度(以字符为单位)

sprintf('%10d', 100)  # => "       100"

# Left-justify if negative.
sprintf('%-10d', 100) # => "100       "

# Ignore if too small.
sprintf('%1d', 100)   # => "100"

精度指定符

精度指定符是一个小数点,后跟零个或多个十进制数字。

对于整数类型指定符,精度指定要写入的最少位数。如果精度短于整数,则结果会用前导零填充。如果整数的长度大于精度,则不会修改或截断结果

sprintf('%.3d', 1)    # => "001"
sprintf('%.3d', 1000) # => "1000"

# If the precision is 0 and the value is 0, nothing is written
sprintf('%.d', 0)  # => ""
sprintf('%.0d', 0) # => ""

对于 a/Ae/Ef/F 指定符,精度指定要写入的小数点后的位数

sprintf('%.2f', 3.14159)  # => "3.14"
sprintf('%.10f', 3.14159) # => "3.1415900000"

# With no precision specifier, defaults to 6-digit precision.
sprintf('%f', 3.14159)    # => "3.141590"

对于 g/G 指定符,精度指定要写入的有效位数

sprintf('%.2g', 123.45)  # => "1.2e+02"
sprintf('%.3g', 123.45)  # => "123"
sprintf('%.10g', 123.45) # =>  "123.45"

# With no precision specifier, defaults to 6 significant digits.
sprintf('%g', 123.456789) # => "123.457"

对于 sp 指定符,精度指定要写入的字符数

sprintf('%s', Time.now)    # => "2022-05-04 11:59:16 -0400"
sprintf('%.10s', Time.now) # => "2022-05-04"

类型指定符详情和示例

指定符 aA

argument 格式化为十六进制浮点数

sprintf('%a', 3.14159)   # => "0x1.921f9f01b866ep+1"
sprintf('%a', -3.14159)  # => "-0x1.921f9f01b866ep+1"
sprintf('%a', 4096)      # => "0x1p+12"
sprintf('%a', -4096)     # => "-0x1p+12"

# Capital 'A' means that alphabetical characters are printed in upper case.
sprintf('%A', 4096)      # => "0X1P+12"
sprintf('%A', -4096)     # => "-0X1P+12"

指定符 bB

当使用标志 '#'+ 时,两个指定符 bB 的行为相同。

argument 格式化为二进制整数

sprintf('%b', 1)  # => "1"
sprintf('%b', 4)  # => "100"

# Prefix '..' for negative value.
sprintf('%b', -4) # => "..100"

# Alternate format.
sprintf('%#b', 4)  # => "0b100"
sprintf('%#B', 4)  # => "0B100"

指定符 c

argument 格式化为单个字符

sprintf('%c', 'A') # => "A"
sprintf('%c', 65)  # => "A"

此行为类似于 String#<<,除了引发 ArgumentError 而不是 RangeError

指定符 d

argument 格式化为十进制整数

sprintf('%d', 100)  # => "100"
sprintf('%d', -100) # => "-100"

标志 '#' 不适用。

指定符 eE

科学计数法格式化 argument

sprintf('%e', 3.14159)  # => "3.141590e+00"
sprintf('%E', -3.14159) # => "-3.141590E+00"

指定符 f

argument 格式化为浮点数

sprintf('%f', 3.14159)  # => "3.141590"
sprintf('%f', -3.14159) # => "-3.141590"

标志 '#' 不适用。

指定符 gG

如果指数小于 -4 或大于等于精度,则使用指数形式(e/E 指定符)格式化 argument。否则,使用浮点形式(f 指定符)格式化 argument

sprintf('%g', 100)  # => "100"
sprintf('%g', 100.0)  # => "100"
sprintf('%g', 3.14159)  # => "3.14159"
sprintf('%g', 100000000000)  # => "1e+11"
sprintf('%g', 0.000000000001)  # => "1e-12"

# Capital 'G' means use capital 'E'.
sprintf('%G', 100000000000)  # => "1E+11"
sprintf('%G', 0.000000000001)  # => "1E-12"

# Alternate format.
sprintf('%#g', 100000000000)  # => "1.00000e+11"
sprintf('%#g', 0.000000000001)  # => "1.00000e-12"
sprintf('%#G', 100000000000)  # => "1.00000E+11"
sprintf('%#G', 0.000000000001)  # => "1.00000E-12"

指定符 o

argument 格式化为八进制整数。如果 argument 为负数,则会将其格式化为前缀为 ..7 的二进制补码

sprintf('%o', 16)   # => "20"

# Prefix '..7' for negative value.
sprintf('%o', -16)  # => "..760"

# Prefix zero for alternate format if positive.
sprintf('%#o', 16)  # => "020"
sprintf('%#o', -16) # => "..760"

指定符 p

通过 argument.inspectargument 格式化为字符串

t = Time.now
sprintf('%p', t)   # => "2022-05-01 13:42:07.1645683 -0500"

指定符 s

通过 argument.to_sargument 格式化为字符串

t = Time.now
sprintf('%s', t) # => "2022-05-01 13:42:07 -0500"

标志 '#' 不适用。

指定符 xX

argument 格式化为十六进制整数。如果 argument 为负数,则会将其格式化为前缀为 ..f 的二进制补码

sprintf('%x', 100)   # => "64"

# Prefix '..f' for negative value.
sprintf('%x', -100)  # => "..f9c"

# Use alternate format.
sprintf('%#x', 100)  # => "0x64"

# Alternate format for negative value.
sprintf('%#x', -100) # => "0x..f9c"

指定符 %

argument ('%') 格式化为单个百分号字符

sprintf('%d %%', 100) # => "100 %"

标志不适用。

按名称引用

对于更复杂的格式化,Ruby 支持按名称引用。 %<name>s 样式使用格式样式,但 %{name} 样式不使用。

示例

sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 }) # => 1 : 2.000000
sprintf("%{foo}f", { :foo => 1 })                      # => "1f"