sprintf格式
Ruby的sprintf格式与C语言的sprintf(3)基本相同。但还是有些差别: 它没有针对C特有类型的修饰符,如short或long等; 它包含2进制数的指示符(%b); 它不支持sprintf的方言式的语法。
下面就对ruby的sprintf格式进行详细的说明。
sprintf格式的规格如下所示。[]
中的部分是可选的。
%[指定参数$][标识符][宽度][.精度]指示符
若想输出`%
'本身时, 请这样`%%
'处理。
下面就分别介绍一下各元素的用法。
标识符
标识符包括`#', `+', ` '(空格), `-'和`0'这5个。
- #
使用2进制、8进制、16进制的指示符(`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" # ".." 表示f无限延续 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', `s', `p'
- 表示整数的指示符: `d', `i', `u', `b', `o', `x', `X',
- 表示浮点数的指示符: `f', `g', `e', `E', `G'
这几类。
- c
将参数的数值(0×255)看作是字符代码,并输出对应的字符。若参数并非数值、String、 nil, true或false的话,将尝试用to_int方法进行变换。
此时,只有标识符`-'和"宽度"的设定是有效的。
- s
输出字符串。
若参数并非String对象的话,将使用to_s方法对其进行变换。
- p
ruby 1.8 特性: 输出Object#inspect的结果。
p sprintf("%s", [1, 2, 3]) # => "123" p sprintf("%p", [1, 2, 3]) # => "[1, 2, 3]"
- d
- i
以10进制整数的形式输出参数中的数值。
若参数并非整数,则使用与Integer函数相同的规则将其变为整数。
- u
将参数的数值看作是无符号整数,并以10进制整数的形式输出它。
p sprintf("%u", -1) # => "..4294967295"
上面的代码会输出 p ".." + 0xffff_ffff.to_s。
ruby 1.7 特性: 在version 1.7中,不会附加".."。若是'%u'的话,则将参数看作是定长整数。此时,对于负整数n来说
printf("%u", n)
与
printf("%d", n & ~(-1 << n.size*8))
是一个意思。
- b
- o
- x
- X
分别以2进制、8进制、16进制、16进制(大写字母)字符串的形式输出整数。
若使用了`#' 标识符的话,则分别在前面添加"0b", "0", "0x", "0X"。
若没有使用`+', ` ' 标识符时,将在负数的前面(若有`#' 标识符,则在"0x"等的后面)添加".."。这表示最高位字符无限延伸,它采用了2的补数形式来表现负数。
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+00" p sprintf("%g", 1.0) # => "1" p sprintf("%f", 10.1) # => "10.100000" p sprintf("%e", 10.1) # => "1.010000e+01" p sprintf("%g", 10.1) # => "10.1" p sprintf("%g", 10 ** 6) # => "1e+06" p sprintf("%g", 10 ** -5) # => "1e-05"
精度的缺省值为6。
若遇到无限大值或NaN(Not a Number)时,输出情况如下。
p sprintf("%f", 1.0/0) # => "inf" p sprintf("%f", -1.0/0) # => "-inf" p sprintf("%f", 0.0/0) # => "nan" p sprintf("%E", 1.0/0) # => "INF" p sprintf("%E", -1.0/0) # => "-INF" p sprintf("%E", 0.0/0) # => "NAN"
指定参数
这部分的利用频率最低,所以放在最后。
- 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"
您也可以先插入"*",然后借用参数来设定"宽度"和"精度"的值。
p sprintf("%5.2f", 1); # => " 1.00" p sprintf("%*.*f", 5, 2, 1); # => " 1.00" p sprintf("%1$*2$.*3$f", 1, 5, 2); # => " 1.00"