2014-01-30 48 views
9

我用這段代碼加載以下.yaml文件的Perl 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文檔中,我認爲這是通過隱式標記處理的,並且模塊會識別十六進制數。

有誰知道如何做到這一點?

+4

這可以說是一個bug,取決於YAML處理器使用哪個[schema](http://www.yaml.org/spec/1.2/spec.html#Schema)(您的程序行爲與Failsafe或JSON一致,但與Core不同)。您可以查看該模塊的[問題](https://rt.cpan.org/Public/Dist/Display.html?Name=YAML),然後查看之前是否報告過這種差異,或者在那裏發現新問題。 – amon

+0

您是否可以安裝並嘗試使用YAML :: XS?當我使用XS版本測試你的yaml輸入時,1沒有被引用。但是,hx值仍被視爲字符串。 – user3183018

+0

我如何測試'/ usr/bin/perl -MYAML :: Any = LoadFile -MData :: Dumper -e'$ y = LoadFile($ ARGV [0]);打印Dumper($ y)。 「\ n」'$ YAMLFILE' – user3183018

回答

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;