格式规范

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"

'n$' 标志

将第 n 个参数(基于 1)格式化到此字段

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('%*d', 20, 14) # => "                  14"

精度说明符

精度说明符是一个小数点,后跟零个或多个小数点数字。

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

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"

如果精度说明符是 '*' 而不是非负整数,则实际精度将从参数列表中获取

sprintf('%.*d', 20, 1)    # => "00000000000000000001"

特定类型说明符的详细信息和示例

说明符 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"