sprintf 格式

Ruby的 sprintf 格式基本上与 C 语言相同。差别是:一、没有针对 C 语言特有类型 short 或 long 的修饰符,二、增加了二进制变量指示字符(%b),三、不完全支持所有 sprintf 的方言式语法。

下面是对于 Ruby 的 sprintf 格式进行详细的说明。

这是 sprintf 的格式,包含在 [] 的表示可以省略。

%[卷标字符][宽度][.精度]指示字符

要输出'%'这个字符就用'%%'。

下面是各个元素的详解。

卷标字符

卷标字符共有五种:'#'、'+'、'(空格)'、' - '、'0'。

#

与二、八、十六进制指示字符('b'、'o'、'x'、'X')同用时,会自动加上对应前缀 '0b'、'0'、'0x'、'0X'。

p sprintf("%#b", 10) # => "0b1010"
p sprintf("%#o", 10) # => "012"
p sprintf("%#x", 10) # => "0xa"
p sprintf("%#X", 10) # => "0XA"

对于浮点数('f'、'e'、'E'、'g' 和'G'),在输出中一定会带有 '.'。

p sprintf("%.0f", 10) # => "10"
p sprintf("%#.0f", 10) # => "10."
p sprintf("%.0e", 10) # => "1e+01"
p sprintf("%#.0e", 10) # => "1.e+01"

除了上述特性,'g'、'G' 会在后面加上剩余的 0。

p sprintf("%.05g", 10) # => "10"
p sprintf("%#.05g", 10) # => "10.000"
+

代表输出的字符会带符号。正数会自动加上'+'号。只对数值指示符('d'、'i'、'b'、'o'、'x'、'X'、'u'、'f'、'e'、'E'、'g'、'G')起作用。另外,对于 'b'、'o'、'x'、'X'、'u',会自动在负数前加上'-'号。

p sprintf("%d", 1) # => "1"
p sprintf("%+d", 1)# => "+1"
p sprintf("%x", -1)# => "..f"# ".." shows that f continues infinitely
p sprintf("%+x", -1) # => "-1"
' '(空格)

与'+'相同,但以空格代替'+'号。只对数值指示符('d'、'i'、'b'、'o'、'x'、'X'、'u'、'f'、'e'、'E'、'g'、'G')起作用。

p sprintf("%d", 1) # => "1"
p sprintf("%+d", 1)# => "+1"
p sprintf("% d", 1)# => " 1"
p sprintf("%x", -1)# => "..f"
p sprintf("% x", 1)# => " 1"
p sprintf("% x", -1) # => "-1"
-

使输出内容靠左对齐,只在已经指定「宽度」时有效。。

0

当输出内容靠右对齐,以'0'替代空格填补多余部分。

只对数值指示符('d'、'i'、'b'、'o'、'x'、'X'、'u'、'f'、'g'、'G')起作用(对 'e' 和 'E' 无效)。

p sprintf("%010d", 10)
# => "0000000010"

与'#'同用时的输出效果:

p sprintf("%#010x", 10)# => "0x0000000a"
p sprintf("%#010o", 10)# => "0000000012"
p sprintf("%#010b", 10)# => "0b00001010"

与下例相同:

p sprintf("%#10.8x", 10) # => "0x0000000a"
p sprintf("%#10.9o", 10) # => "0000000012"
p sprintf("%#10.8b", 10) # => "0b00001010"

一般情况下会显示:

p sprintf("%#10x", 10) # => " 0xa"
p sprintf("%#10o", 10) # => " 012"
p sprintf("%#10b", 10) # => "0b1010"

宽度

任何以非 0 开头的数字字符串指定宽度。宽度是指字符串显示出来的宽度。不受下文的「精度」影响。

宽度包含了由「卷标字符」添加的 ' '、'+'、'-'、'0b'、'0'、'0x'、'0X' 的宽度。

p sprintf("%#05x", 10) # => "0x00a"

宽度是指「需要的最小宽度」。若结果的数字字符串超过指定的宽度,则会无视宽度的设置。

若宽度设为 '*',则使用参数指定宽度值。

p sprintf("%10s", "foo")    # => "       foo"
p sprintf("%*s", 10, "foo") # => "       foo"

精度

接续在 '.' 之后的数字串表示精度。(若是只有'.' ,就与'.0'相同)。若与整数的指示字符('d'、'i'、'b'、'o'、'x'、'X'、'u')同用的话,精度表示数值部分的长度。

p sprintf("%10.5d", 1)# => " 00001"
p sprintf("%#10.5x", 1) # => " 0x00001"
p sprintf("%+10.5x", 1) # => "+00001"

若与浮点数的指示字符('f')同用,表示小数点后的位数。

p sprintf("%10.5f", 1) # => " 1.00000"
p sprintf("%10.5f", 10)# => "10.00000"

若与浮点数的指示字符('e'、'E'、'g'、'G')同用,表示浮点数的有效位数。

p sprintf("%10.5e", 1) # => "1.00000e+00"
p sprintf("%10.5e", 10)# => "1.00000e+01"
p sprintf("%10.5g",10)# => "10"
p sprintf("%#10.5G", 10)# => "10.000"

若与字符串的指定字符('s'、'p')同用,则参数字符串超出长度的部分会被切除。若宽度与精度相同,则只会输出该长度的部分。

p sprintf("%10.2s", "foo")# => "fo"
p sprintf("%5.5s", "foo") # => # => "foo"
p sprintf("%5.5s", "foobar")# => # => "fooba"

若精度设为 '*',则使用参数指定精度值。

p sprintf("%.5s", "foobar")# => "fooba"
p sprintf("%.*s", 5, "foobar") # => "fooba"

指示字符

指出参数的类型。不可以被省略,分成下面几类:

c

将参数的数值(0~255)视为字符代码,并输出相对应的字符。若参数非数值、String、nil、true、false,则会尝试使用 to_int 方法进行转换。

只有卷标字符 '-' 和「宽度」有意义。

s

输出字符串。

若参数非 String 对象,则使用 to_s 方法将参数对象转成字符串。

p

输出 Object#inspect 的结果。

p sprintf("%s", [1, 2, 3])# => "123"
p sprintf("%p", [1, 2, 3])# => "[1, 2, 3]"
d
i

将参数值以 10 进制整数输出。

若参数非整数则转换为整数。

u

将参数值视为无符号整数,并以 10 进制整数输出。

p sprintf("%u", -1) # => "4294967295"

会输出 p 0xffff_ffff.to_s。

'%u' 将参数视为定长整数,而对于负整数 n 来说,

printf("%u", n)

相当于

printf("%d", n & ~(-1 << n.size*8))
b
o
x
X

将整数以二进制、八进制、十六进制、(大写)十六进制的字符串输出。

若指定了卷标字符 '#' 时,会分别在前方加上' 0b'、'0'、'0x'、'0X'。

若没有使用卷标字符 '+' 或 ' ',就会在负数的前面添加 '..'(若使用了'#'标签,则是在 '0x' 等之后)。这表示最高位数的字符无限延伸,因为负数是使用二补码显示的。

p sprintf("%#b", 10)# => "0b1010"
p sprintf("%#o", 10)# => "012"
p sprintf("%#x", 10)# => "0xa"
# ".." 添加在负数前方
p sprintf("%#b", -1)# => "0b..1"
p sprintf("%#o", -1)# => "0..7"
p sprintf("%#x", -1)# => "0x..f"
p sprintf("%10x", -1) # => " ..f"
p sprintf("%-10x", -1)# => "..f "
# 指定精度时,不会添加 ".."
p sprintf("%.10x", -1)# => "ffffffffff"
f
e
E
g
G

'f' 将数值以小数形式输出(xxx.xxx)。

'e' 将数值以指数形式输出(x.xxxe+xx)。

'g' 在指数小于 -4 或大于精度时与 'e' 相同,否则与 'f' 相同。但是小数之后的 0 会省略。

使用大写('E'、'G')时,会使用大写字母输出。

p sprintf("%f", 1.0) # => "1.000000"
p sprintf("%e", 1.0) # => "1.000000e+000"
p sprintf("%g", 1.0) # => "1"
p sprintf("%f", 10.1) # => "10.100000"
p sprintf("%e", 10.1) # => "1.010000e+001"
p sprintf("%g", 10.1) # => "10.1"
p sprintf("%g", 10 ** 6)# => "1e+006"
p sprintf("%g", 10 ** -5) # => "1e-005"

默认的精度值为 6。

指定参数

并不常使用,因此最后解释。

nth$

指定第 nth 个执行的参数。

p sprintf("%1$d, %1$x, %1$o", 10)
=> "10, a, 12"
p sprintf("%3$d, %2$x, %1$o", 1, 2, 3)
=> "3, 2, 1"

当想要依照场合改变格式,又不想要变更参数的顺序时可以使用。

case ENV['LC_TIME']
when /^ja_JP/
 fmt = "%1$d年%2$d月%3$d日"
else
 fmt = "%2$02d/%03$2d/%1$02d"
end
p sprintf(fmt, 1, 4, 22)
=> "04/22/01"