为什么 Ruby 将整数转换为八进制转义字符串而不是十六进制转义字符串?
Why does Ruby convert integer to octal-escaped string instead of hex-escaped one?
我需要:
"ff".hex.chr #=> "\xff"
但我得到的是:
"ff".hex.chr #=> "7"
我的错误在哪里?什么不见了?环境是HBase 0.98.6 shell,好像是基于JRuby 1.6.8 console.
"\xff"
和"7"
是同一数据的不同表示:
"\xff"
是十六进制,是较新的 Ruby 版本的典型值。
"7"
是八进制,是旧 Ruby 版本的典型值。
您可以看到相同的数字如何产生不同的字符串:
printf("%o",255) #=> "377"
printf("%x",255) #=> "ff"
默认表示通常是由于您的控制台设置和 Ruby 版本。
一般来说,即使在相同的 Ruby 版本上,也不要依赖 String#inspect
来产生一致的表示。如果您使用一些特殊字符,您可以看到实际效果:
"[=11=]7" #=> "\a"
String#inspect
方法已将表示形式更改为既不是八进制也不是十六进制。
如果您要输出到需要特定格式的系统,您可以明确:
printf("\x%x", 255) #=> \xff # lower case
printf("\x%X", 255) #=> \xFF # upper case
您也可以尝试pack
和unpack
方法:
["ff"].pack("H*") #=> "\xFF"
如果你的字符串总是十六进制数字,而你想要的输出只是在每两个字符前插入“\x”,那么有一个快速的解决方案:
print "a1b2c3".gsub(/../){"\x#{$&}"}
#=> \xa1\xb2\xc3
Ruby 字符串表示以及如何使用不可打印字符的快速介绍在 Safari Books Ruby Cookbook
经验教训:
- 实际上八位字节没有任何功能问题。只是表示(感谢所有评论和答案)。内部字符串内容相同。
- 是的,在 Ruby 1.8 中有格式为“%03o”的 String#inspect。是的,HBase 0.98.6 将此 Ruby 版本用于 JRuby 1.6.8。就我而言,这不容易解决。
- 检查与实际结果无关,所以我使用了 Hbase
Bytes
class 并为需要查看预期键表示的人准备了特殊的 printer
。
这是实际解决我所有任务的代码,包括需要的输出:
# Convert binary string to hex digits.
def bin_to_hex(s)
s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
end
# Convers hex string to binary string.
def hex_to_bin(s)
s.scan(/../).map { |x| x.hex.chr }.join
end
# HBase special 'convert and print' routine to get hex digits, process them and print.
def print_hex_to_bin(s)
Kernel.print "\"" + Bytes.toStringBinary(s.scan(/../).map { |x| x.hex.chr }.join.to_java_bytes) + "\"\n"
end
主要基于http://anthonylewis.com/2011/02/09/to-hex-and-back-with-ruby/
组成
我需要:
"ff".hex.chr #=> "\xff"
但我得到的是:
"ff".hex.chr #=> "7"
我的错误在哪里?什么不见了?环境是HBase 0.98.6 shell,好像是基于JRuby 1.6.8 console.
"\xff"
和"7"
是同一数据的不同表示:
"\xff"
是十六进制,是较新的 Ruby 版本的典型值。"7"
是八进制,是旧 Ruby 版本的典型值。
您可以看到相同的数字如何产生不同的字符串:
printf("%o",255) #=> "377"
printf("%x",255) #=> "ff"
默认表示通常是由于您的控制台设置和 Ruby 版本。
一般来说,即使在相同的 Ruby 版本上,也不要依赖 String#inspect
来产生一致的表示。如果您使用一些特殊字符,您可以看到实际效果:
"[=11=]7" #=> "\a"
String#inspect
方法已将表示形式更改为既不是八进制也不是十六进制。
如果您要输出到需要特定格式的系统,您可以明确:
printf("\x%x", 255) #=> \xff # lower case
printf("\x%X", 255) #=> \xFF # upper case
您也可以尝试pack
和unpack
方法:
["ff"].pack("H*") #=> "\xFF"
如果你的字符串总是十六进制数字,而你想要的输出只是在每两个字符前插入“\x”,那么有一个快速的解决方案:
print "a1b2c3".gsub(/../){"\x#{$&}"}
#=> \xa1\xb2\xc3
Ruby 字符串表示以及如何使用不可打印字符的快速介绍在 Safari Books Ruby Cookbook
经验教训:
- 实际上八位字节没有任何功能问题。只是表示(感谢所有评论和答案)。内部字符串内容相同。
- 是的,在 Ruby 1.8 中有格式为“%03o”的 String#inspect。是的,HBase 0.98.6 将此 Ruby 版本用于 JRuby 1.6.8。就我而言,这不容易解决。
- 检查与实际结果无关,所以我使用了 Hbase
Bytes
class 并为需要查看预期键表示的人准备了特殊的printer
。
这是实际解决我所有任务的代码,包括需要的输出:
# Convert binary string to hex digits.
def bin_to_hex(s)
s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
end
# Convers hex string to binary string.
def hex_to_bin(s)
s.scan(/../).map { |x| x.hex.chr }.join
end
# HBase special 'convert and print' routine to get hex digits, process them and print.
def print_hex_to_bin(s)
Kernel.print "\"" + Bytes.toStringBinary(s.scan(/../).map { |x| x.hex.chr }.join.to_java_bytes) + "\"\n"
end
主要基于http://anthonylewis.com/2011/02/09/to-hex-and-back-with-ruby/
组成