perl:命名从YAML读取的哈希变量

时间:2013-03-21 23:53:25

标签: perl yaml

我正在阅读YAML文件中的一些信息

groceries.yaml

# comment
fruit:
   apples: 1
   oranges: 1
   grapes: 1
vegetables:
   potatoes: 1
   onions: 1
   leeks: 1

加入perl脚本

myscript.pl

#!/usr/bin/perl

use strict;
use warnings;
use YAML::Tiny;

# Create a YAML file
my $stuff = YAML::Tiny->new;

# Open the config
$stuff = YAML::Tiny->read( 'groceries.yaml' );

print "Fruit: ", %{($stuff->[0]->{fruit})},"\n";
print "Vegetables: ", %{($stuff->[0]->{vegetables})},"\n";

exit

这很好用,但我希望fruit有一个哈希值,vegetables有一个哈希值。我天真的尝试是

my @keys = keys %{($stuff->[0])};
foreach my $key (@keys){
        my %{ $key }  = %{($stuff->[0]->{$key})},"\n";
}

但显然这不起作用。

我很想了解我做错了什么,并且愿意接受不同的工作流程来实现同样的想法:)

3 个答案:

答案 0 :(得分:2)

试试这个:

#!/usr/bin/perl

use strict;
use warnings;
use YAML::Tiny;
use Data::Dumper;

# Create a YAML file
my $stuff = YAML::Tiny->new;

# Open the config
$stuff = YAML::Tiny->read( 'groceries.yaml' ); 

my %fruits = %{ $stuff->[0]->{fruit} };
my %vegetables = %{ $stuff->[0]->{vegetables} };

我不知道你为什么在代码中添加了一些括号:

%{($stuff->[0]->{$key})},"\n";

我认为这是问题。


迭代HASH,

use Data::Dumper;
# ...
foreach my $key (keys %{ $stuff->[0] }) {
    print Dumper $stuff->[0]->{$key};
}

EDIT2

#!/usr/bin/perl

use strict;
use warnings;
use YAML::Tiny;
use Data::Dumper;

# Create a YAML file
my $stuff = YAML::Tiny->new;

# Open the config
$stuff = YAML::Tiny->read( 'groceries.yaml' );

my %top_h;

foreach my $key (keys %{ $stuff->[0] }) {
    $top_h{$key} = $stuff->[0]->{$key};
}

print Dumper \%top_h;

答案 1 :(得分:2)

此解决方案可让您访问%fruit%vegetables。它们使用our声明为包全局变量,以便它们位于符号表中,然后允许您使用符号引用或全局赋值。您还需要关闭strict refs才能启用此功能。另请参阅this reference

use strict;
use warnings;
use YAML::Tiny;
use Data::Dumper;

my $stuff = YAML::Tiny->read('groceries.yml');

my %groceries = %{$stuff->[0]};

our %fruit;
our %vegetables;
{
    no strict 'refs'; 
    #no strict 'vars'; # don't need above 'our' declarations with this
    while (my ($key, $val) = each %groceries) {
        %$key = %$val;
        # or *$key = $val;
    }
}

print Dumper \%fruit;

如果您不知道前面的密钥,那么您还需要关闭strict vars,这样您就不需要在分配哈希值之前声明哈希值。但是当你直接使用哈希时,你可能会收到警告。

但是,尽管如此,我认为使用%groceries最简单。

答案 2 :(得分:1)

my ( $fruit, $vegetables) = @{$stuff->[0]}{ qw<fruit vegetables> };

如果你想循环执行此操作,首先,我会将第一个“文档”保存到本地引用。

my $yaml = $stuff->[0];

然后在while循环中,执行此操作:

while ( my ( $k, $v ) = each %$yaml ) {
    say ucfirst( $k ) . ': ' . %$v;
}

您也可以使用List::Pairwise并执行此操作:

mapp { say ucfirst( $a ) . ': ' . %$b } %{ $stuff->[0] };