Perl YAML模块无法识别标量类型

时间:2014-01-30 16:21:55

标签: perl yaml

我加载了以下.yaml文件

foo : bar
s : 1
hx: 0x34

使用这段代码:

use YAML qw(LoadFile Dump); 
use Data::Dumper; 
my $d=LoadFile("test.yaml"); 
print Dumper($d);
print "x        =", $d->{hx},"\n";
print "x/2      =", $d->{hx}/2,"\n";
print "hex(x)/2 =", hex($d->{hx})/2,"\n";

,输出

Output:
> ./yaml.pl
$VAR1 = {
          'foo' => 'bar',
          'hx' => '0x34',
          's' => '1'
        };
x        =0x34
x/2      =0
hex(x)/2 =26

这意味着它将所有标量视为字符串,这是我没想到的。从CPAN http://metacpan.org/pod/YAML的YAML文档中,我假设这是通过隐式标记处理的,并且模块将识别十六进制数。

有人知道怎么做吗?

1 个答案:

答案 0 :(得分:2)

如果检查加载器类,您会发现_parse_inline子组有一些分支,用于序列,映射,单引号和双引号字符串以及其他一些情况。您需要做的就是为以0x开头的值添加分支。我写了那个分支和一个用于处理YAML 0.900.0的十六进制值的子程序。我尝试了一些基本的输入,它似乎做你想要的。如果它也适合您,请考虑提交补丁。

dump.pl

use YAML qw(LoadFile Dump); 
use Data::Dumper; 
my $d=LoadFile("test.yaml"); 
$d=LoadFile("test.yaml"); 
print Dumper($d);
print "x        =", $d->{hx},"\n";
print "x/2      =", $d->{hx}/2,"\n";
print "hex(x)/2 =", hex($d->{hx})/2,"\n";



$d=LoadFile("sym1.yaml"); 
print Dumper($d);

print "dodo[4]  =", $d->{dodo}->{doto}[4], "\n";
print "dodo[3]  =", $d->{dodo}->{doto}[3], "\n";

sym1.yaml

"symfony 1.0":
  PHP:    5.0
  Propel: 1.2
"symfony 1.2":
  PHP:    5.2
  Propel: 1.3

dodo:
  doto: [1,23,4, 0x34, 0x16 ]
  dozo: [1,23,4, 0x12, 0x11 ]
  dofo: { a: 2,  358: 0x166, 255: 0xff, 255: 0xFF}
ffa: 0xFfA

$ perl dump.pl

$VAR1 = {
          'foo' => 'bar',
          'hx' => 52,
          's' => '1'
        };
x        =52
x/2      =26
hex(x)/2 =41
$VAR1 = {
          'ffa' => 4090,
          'symfony 1.2' => {
                           'PHP' => '5.2',
                           'Propel' => '1.3'
                         },
          'dodo' => {
                    'dofo' => {
                              'a' => '2',
                              '255' => 255,
                              '358' => 358
                            },
                    'dozo' => [ '1','23', '4', 18, 17 ],
                    'doto' => [ '1', '23', '4', 52, 22 ]
                  },
          'symfony 1.0' => {
                           'PHP' => '5.0',
                           'Propel' => '1.2'
                         }
        };

doto[4]  =22
doto[3]  =52

YAML 0.900.0的补丁

diff --git a/Loader.pm b/Loader.pm
index 3bf20c7..d7096df 100644
--- a/Loader.pm
+++ b/Loader.pm
@@ -437,6 +437,10 @@ sub _parse_inline {
         $node = $self->_parse_inline_single_quoted();
         $node = $self->_parse_implicit($node) if $implicit;
     }
+    elsif ($self->inline =~ /^0x/) {
+        $node = $self->_parse_inline_single_hex();
+        # do something if implicit?
+    }
     else {
         if ($top) {
             $node = $self->inline;
@@ -541,6 +545,21 @@ sub _parse_inline_single_quoted {
     return $node;
 }

+# Parse the inline hex value
+sub _parse_inline_single_hex {
+    my $self = shift;
+    my $node;
+    if ($self->inline =~ /^0x([A-Fa-f0-9]+)(,?.*)?$/) {
+        $node = hex($1);
+        $self->inline($2);
+        $node =~ s/''/'/g;
+    }
+    else {
+        $self->die('YAML_PARSE_ERR_BAD_HEX');
+    }
+    return $node;
+}
+
 # Parse the inline unquoted string and do implicit typing.
 sub _parse_inline_simple {
     my $self = shift;