sprintf格式
Ruby的sprintf格式与C语言的sprintf(3)基本相同。但还是有些差别: 它没有针对C特有类型的修饰符,如short或long等; 它包含2进制数的指示符(%b); 它不支持sprintf的方言式的语法。
下面就对ruby的sprintf格式进行详细的说明。
sprintf格式的规格如下所示。[]
中的部分是可选的。
1 | %[指定参数$][标识符][宽度][.精度]指示符
|
若想输出`%
'本身时, 请这样`%%
'处理。
下面就分别介绍一下各元素的用法。
标识符
标识符包括`#', `+', ` '(空格), `-'和`0'这5个。
- #
-
使用2进制、8进制、16进制的指示符(`b', `o', `x', `X')时, 会分别添加"0b", "0", "0x", "0X"前缀。
1 2 3 4 | 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'), 则必定在输出中添加"."。
1 2 3 4 | 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。
1 2 | 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'的话, 则会为负数添加`-'。
1 2 3 4 5 | 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')起作用。
1 2 3 4 5 6 7 | 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'无效)
1 2 | p sprintf( "%010d" , 10)
# => "0000000010"
|
与`#'一起使用时, 输出情况如下。
1 2 3 | p sprintf( "%#010x" , 10) # => "0x0000000a"
p sprintf( "%#010o" , 10) # => "0000000012"
p sprintf( "%#010b" , 10) # => "0b00001010"
|
它等同于下例。
1 2 3 | p sprintf( "%#10.8x" , 10) # => "0x0000000a"
p sprintf( "%#10.9o" , 10) # => "0000000012"
p sprintf( "%#10.8b" , 10) # => "0b00001010"
|
通常情况下, 会输出如下内容。
1 2 3 | p sprintf( "%#10x" , 10) # => " 0xa"
p sprintf( "%#10o" , 10) # => " 012"
p sprintf( "%#10b" , 10) # => " 0b1010"
|
宽度
以非0数字开头的数串负责指定宽度。宽度是指生成字符串的宽度, 它不受后文中的精度的限制。
确定宽度时, 也会考虑标识符中附加的" ", "+","-", "0b", "0", "0x", "0X"的长度。
1 | p sprintf( "%#05x" , 10) # => "0x00a"
|
宽度是指"必要的最小宽度". 若结果字符串的宽度超过指定宽度时, 指定宽度就会失效。
若将宽度指定为`*'时, 将从参数中取得宽度值。
1 2 | p sprintf( "%10s" , "foo" ) # => " foo"
p sprintf( "%*s" , 10, "foo" ) # => " foo"
|
精度
紧跟在"."后面的数串表示精度(若只有"."的话,则为".0")。若遇到整数的指示符(`d', `i', `b', `o', `x', `X', `u')的话,精度表示数值部分的长度。
1 2 3 | p sprintf( "%10.5d" , 1) # => " 00001"
p sprintf( "%#10.5x" , 1) # => " 0x00001"
p sprintf( "%+10.5x" , 1) # => " +00001"
|
若遇到浮点数的指示符(`f')的话,它表示小数部分的位数。
1 2 | p sprintf( "%10.5f" , 1) # => " 1.00000"
p sprintf( "%10.5f" , 10) # => " 10.00000"
|
若遇到浮点数的指示符(`e', `E', `g', `G')的话,它表示有效位数。
1 2 3 4 | 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')的话,将会按照精度的规定来检查参数中的字符串长度,并切除多余部分。若将宽度和精度设为同值的话,则只输出参数字符串中的符合精度规定的部分。
1 2 3 4 | p sprintf( "%10.2s" , "foo" ) # => " fo"
p sprintf( "%5.5s" , "foo" ) # => # => " foo"
p sprintf( "%5.5s" , "foobar" ) # => # => "fooba"
|
若将精度设为`*'的话,将从参数中提取精度的值。
1 2 | 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的结果。
1 2 | p sprintf( "%s" , [1, 2, 3]) # => "123"
p sprintf( "%p" , [1, 2, 3]) # => "[1, 2, 3]"
|
- d
- i
-
以10进制整数的形式输出参数中的数值。
若参数并非整数,则使用与Integer函数相同的规则将其变为整数。
- u
-
将参数的数值看作是无符号整数,并以10进制整数的形式输出它。
1 | p sprintf( "%u" , -1) # => "..4294967295"
|
上面的代码会输出 p ".." + 0xffff_ffff.to_s。
ruby 1.7 特性: 在version 1.7中,不会附加".."。若是'%u'的话,则将参数看作是定长整数。此时,对于负整数n来说
与
1 | printf( "%d" , n & ~(-1 << n.size*8))
|
是一个意思。
- b
- o
- x
- X
-
分别以2进制、8进制、16进制、16进制(大写字母)字符串的形式输出整数。
若使用了`#' 标识符的话,则分别在前面添加"0b", "0", "0x", "0X"。
若没有使用`+', ` ' 标识符时,将在负数的前面(若有`#' 标识符,则在"0x"等的后面)添加".."。这表示最高位字符无限延伸,它采用了2的补数形式来表现负数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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')会将输出中的字母变为大写形式。
1 2 3 4 5 6 7 8 9 10 | 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)时,输出情况如下。
1 2 3 4 5 6 7 | 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个参数进行格式化操作。
1 2 3 4 5 | 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"
|
若您不想改变参数的顺序而只想改变格式的话,也可以使用它。
1 2 3 4 5 6 7 8 9 | 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"
|
您也可以先插入"*",然后借用参数来设定"宽度"和"精度"的值。
1 2 3 | 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"
|