Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl和Ruby之间的YAML数据交换问题_Ruby_Perl_Yaml - Fatal编程技术网

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

Perl和Ruby之间的YAML数据交换问题,ruby,perl,yaml,Ruby,Perl,Yaml,我在Perl和Ruby之间通过YAML交换数据时遇到了问题。我有一些看起来像number:number的值,比如1:16 Perl的YAML库(Tiny和XS)将其编码为1:16,不带引号。Ruby的YAML库(Psych)没有将其解释为字符串,而是以某种方式变成了Fixnum值4560。我不知道如何解决这两方面的转换问题 对于我的用例,YAML中的每个值都应该是一个对象或字符串。因此,如果存在这样的选项,我可以告诉Perl YAML库引用所有值。或者有没有办法告诉Ruby YAML库将所有值解

我在Perl和Ruby之间通过YAML交换数据时遇到了问题。我有一些看起来像number:number的值,比如
1:16

Perl的YAML库(Tiny和XS)将其编码为
1:16
,不带引号。Ruby的YAML库(Psych)没有将其解释为字符串,而是以某种方式变成了Fixnum值
4560
。我不知道如何解决这两方面的转换问题

对于我的用例,YAML中的每个值都应该是一个对象或字符串。因此,如果存在这样的选项,我可以告诉Perl YAML库引用所有值。或者有没有办法告诉Ruby YAML库将所有值解释为字符串?有什么想法吗

从逻辑上讲,更改任何一方的语言都不是一个选项

Perl:

红宝石:


Ruby代码将打印
4560
。其中一条评论解释了如何从
1:16
获得
4560
,它是1小时16分钟转换成秒的。嗯,好的。

Ruby将所有YAML条目解释为字符串,除非它们合适。条目
1:16
看起来与特殊格式匹配了一段时间,因此Ruby错误地解释了它

您需要强制Ruby将字段解释为字符串。有两种方法可以做到这一点。以下任一YAML输出应为您提供所需的结果:

abc: !str 1:16
abc: '1:16'
要生成此输出,请尝试以下Perl代码:

my $foo={'abc'=>'!str 1:16'};
my $foo={'abc'=>"'1:16'"};
更新: 我能够使用以下代码在Perl和Ruby之间传递数据:

Perl:

红宝石:


结果使用起来比加载文件返回的简单散列要复杂一些,但看起来它至少像预期的那样解析了文件。

正在使用的解析器中有一个bug。它似乎认为
1:16
是某种时间(因为4560是一小时16分钟内的秒数),但我发现没有任何东西可以验证这种解释

最好的解决方案是使用一个没有bug的解析器

  • YAML::XS使用的
    libyaml
    ,据说有Ruby绑定
  • YAML::Syck使用的
    libsyck
    ,据说有Ruby绑定
另一种方法是生成总是引用字符串的YAML(或者至少当字符串被视为时间时)

有一个选项可以完全做到这一点

$ perl -e'
   use YAML::Syck qw( Dump );
   local $YAML::Syck::SingleQuote = 1;
   print(Dump({abc=>"1:16"}));
'
--- 
"abc": '1:16'
(不知道我之前怎么错过了这个选项!)

根据,
1:16
是一个六进制(60进制)格式的整数

另请参见,其中说明:

使用“:”允许以60为基数表示整数,这便于时间和角度值

Ruby,Psych中包含的Yaml解析器(错误地说,
1:16
应该是71–Psych代码似乎认为所有这些值都将以
a:b:c
的形式出现,但regex没有强制执行)。Perl发射器(至少是我测试过的YAML::XS)无法识别这种格式,因此在编写文件时不会引用字符串。XS确实识别并引用了一些整数,但不是全部。XS也不能识别Psych所能识别的许多其他格式(例如日期)

(似乎是sexagesimal格式。)

Psych在解析方面有很大的灵活性–
YAML.load\u file
只是一个用于常见用例的简单接口

您可以使用Psych的
parse
方法创建yaml的树表示,然后使用自定义
ScalarScanner
将其转换为Ruby数据结构(该对象将特定格式的字符串转换为适当的Ruby类型):

require('yaml'))
类MyScalarScanner
这与使用
YAML.load_file
时发生的过程基本相同,只是它使用自定义的scanner类

类似的替代方法是打开
ScalarScanner
,用定制的方法替换
tokenize
方法。这将允许您使用更简单的
load_file
接口,但需要注意猴子补丁类:

class Psych::ScalarScanner
别名:orig_tokenize:tokenize
def标记化字符串
如果字符串=~/^[-+]?[0-9][0-9\]*(:[0-5]?[0-9]),则返回字符串+$/
原始标记化字符串
结束
结束
foo=YAML.load_文件'test.YAML'

请注意,这些示例仅考虑具有类似
1:16
格式的值。根据Perl程序发出的内容,您可能还需要覆盖其他模式。您可能特别想了解的是sexagesimal浮点(例如,
1:16.44
)。

能否提供一些YAML数据示例以及用于解码的Ruby和Perl代码?4560是一小时16分钟内的秒数(假设没有闰秒)。生成的YAML文件是什么样子的?@bta,由于它是由
“--\nabc:1:16\n”
生成的,所以我可以说,问题出在Ruby方面。您是否可以使用另一个解析器?它正确地生成
abc:'!str 1:16'
abc:'1:16'
。我相信这两种格式都不会在Ruby中产生正确的结果。
1:16
与您链接的文档中列出的任何格式都不匹配。@ikegami-它只与格式匹配了一段时间,尽管该页面上的有限示例使用了更复杂的示例。Ruby为日期和时间对象提供了许多可能的输出格式选项,YAML解析器似乎正在标记任何可能是日期的内容。我的Perl技能非常生疏,因此您可能需要调整它以在fo中获得YAML输出
my $foo={'abc'=>'!str 1:16'};
my $foo={'abc'=>"'1:16'"};
use YAML::XS qw(DumpFile);
my $foo={'abc'=>'1:16'};
DumpFile('test.yaml',$foo);
require 'yaml'
foo=YAML.parse_file('test.yaml')
foo['abc'].value
=> "1:16"
foo['abc'].value.class
=> String
$ perl -e'
   use YAML::Syck qw( Dump );
   local $YAML::Syck::SingleQuote = 1;
   print(Dump({abc=>"1:16"}));
'
--- 
"abc": '1:16'