我在使用YAML在Perl和Ruby之间交换数据时遇到了麻烦.我有一些看起来像数字的值:数字,如1:16.
Perl的YAML库(Tiny和XS)将其编码为1:16无引号.Ruby的YAML库(Psych)不会将其解释为字符串,而是以某种方式成为Fixnum值4560.我无法弄清楚如何修复任何一方的转换问题.
我的用例的YAML中的每个值都应该是一个对象或字符串.所以,如果存在这样的选项,我可以告诉Perl YAML库引用所有值.或者有没有办法告诉Ruby YAML库将所有值都解释为字符串?有任何想法吗?
改变任何一方的语言在逻辑上都不是一种选择.
Perl的:
use YAML::XS qw(DumpFile);
my $foo={'abc'=>'1:16'};
DumpFile('test.yaml',$foo);
Run Code Online (Sandbox Code Playgroud)
红宝石:
require('yaml')
foo=YAML.load_file('test.yaml')
puts(foo['abc'])
Run Code Online (Sandbox Code Playgroud)
Ruby代码将打印出来4560.其中一条评论了解了你是如何得出4560的1:16,它是1小时16分转换为秒.呃,好的.
根据Yaml 1.1规范,1:16是sexagesimal(base 60)格式的整数.
另见http://yaml.org/type/int.html,其中说:
使用":"允许在基数60中表示整数,这便于时间和角度值.
包含在Ruby,Psych中的Yaml解析器识别这种格式并将值转换为整数(错误地,1:16应该是71-精神代码似乎假设所有这些值都将在形式中,a:b:c但正则表达式不强制执行) .Perl发射器(至少我测试过的YAML :: XS)无法识别这种格式,所以在编写文件时不引用字符串.YAML :: XS 确实识别并引用一些整数,但不是全部.YAML :: XS也不承认Psych所做的许多其他格式(例如日期).
(似乎已经从Yaml 1.2规范中删除了sexagesimal格式.)
Psych在解析时提供了相当大的灵活性 - YAML.load_file只是常见用例的简单接口.
您可以使用parsePsych 的方法创建yaml的树表示,然后使用自定义ScalarScanner(将某些格式的字符串转换为适当的Ruby类型的对象)将其转换为Ruby数据结构:
require('yaml')
class MyScalarScanner < Psych::ScalarScanner
def tokenize string
#this is the same regexp as Psych uses to detect base 60 ints:
return string if string =~ /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
super
end
end
tree = YAML::parse_file 'test.yaml'
foo = Psych::Visitors::ToRuby.new(MyScalarScanner.new).accept tree
Run Code Online (Sandbox Code Playgroud)
这基本上与您使用时发生的过程相同YAML.load_file,只是它使用自定义扫描程序类.
类似的替代方案是打开ScalarScanner并用tokenize自定义方法替换该方法.这将允许您使用更简单的load_file界面,但有关于猴子修补类的常见警告:
class Psych::ScalarScanner
alias :orig_tokenize :tokenize
def tokenize string
return string if string =~ /^[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+$/
orig_tokenize string
end
end
foo = YAML.load_file 'test.yaml'
Run Code Online (Sandbox Code Playgroud)
请注意,这些示例仅考虑具有类似格式的值1:16.根据您的Perl程序发出的内容,您可能还需要覆盖其他模式.你可能想要看的一个特别是性感浮动(例如1:16.44).
| 归档时间: |
|
| 查看次数: |
717 次 |
| 最近记录: |