ruby - Perl 和 Ruby 之间的 YAML 数据交换问题

标签 ruby perl yaml

我在通过 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);

ruby :

require('yaml')
foo=YAML.load_file('test.yaml')
puts(foo['abc'])

Ruby 代码将打印 4560。其中一条评论说明了如何从 1:16 得到 4560,即 1 小时 16 分钟转换为秒。嗯,好的。

最佳答案

根据Yaml 1.1 spec , 1:16 是一个六十进制(以 60 为底)格式的整数。

另见 http://yaml.org/type/int.html ,它说:

Using “:” allows expressing integers in base 60, which is convenient for time and angle values.

Ruby、Psych 中包含的 Yaml 解析器,recognises this format and converts the value into an integer (错误地,1:16 应该是 71——Psych 代码似乎假设所有这些值都将采用 a:b:c 的形式,但正则表达式并不强制执行)。 Perl 发射器(至少我测试过的 YAML::XS)不识别这种格式,所以在写入文件时不引用字符串。 YAML::XS 确实识别并引用了一些整数,但不是全部。 YAML::XS 也无法识别 Psych 可以识别的许多其他格式(例如日期)。

(好像是六十进制格式has been removed from the Yaml 1.2 spec。)

Psych 在其解析中提供了相当大的灵 active ——YAML.load_file 只是常见用例的简单接口(interface)。

您可以使用 Psych 的 parse 方法创建 yaml 的树表示,然后使用自定义 ScalarScanner(这是将特定格式的字符串转换为适当的 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

这与使用 YAML.load_file 时发生的过程基本相同,只是它使用了自定义的扫描器类。

类似的替代方法是打开 ScalarScanner 并将 tokenize 方法替换为自定义方法。这将允许您使用更简单的 load_file 接口(interface),但带有关于猴子修补类的常见警告:

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'

请注意,这些示例仅考虑格式为 1:16 的值。根据您的 Perl 程序发出的内容,您可能还需要覆盖其他模式。您可能特别想看看的一个是六十进制 float (例如 1:16.44)。

关于ruby - Perl 和 Ruby 之间的 YAML 数据交换问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12610187/

相关文章:

java - 从映射转换为 yaml 时,Snake yaml 转储器选项会为带有空格的字符串生成不必要的转义空格字符 ("\")

ruby-on-rails - 通过先写入 redis 来加速 web 服务,然后写入磁盘?

javascript 改变 ruby​​ 变量

regex - 用 & 替换 & 的正则表达式

mysql - perl错误处理中加载数据infile mysql语句

macos - YAML异常: unacceptable character '' (0x0)

ruby - 我想用 ruby​​ 在一行文本中搜索给定的单词

ruby-on-rails - 在 Ubuntu 上安装 RMagick 和 ImageMagick 有技巧吗?

perl - 如何包含 Template::Toolkit- Macros?

java - YAML Mapper 如何在反序列化过程中忽略 yml 文件中的某些字段?