加载yaml文件后访问perl中的数据

时间:2016-11-20 13:27:29

标签: arrays perl hash yaml

我必须解析yaml并处理perl中的数据。

我的yaml文件如下所示:

route1:
    dst:
       - atl
    src:
       - bos
route2:
    dst:
       - sfo
    src:
       - dal

我的解析脚本如下所示:

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

    open my $fh, '<', 'testcase'
        or die "can't open file';

     my(@routes) = YAML::LoadFile($fh);
     print Dumper(@routes), "\n";

这个输出看起来像我期待的那样

     $VAR1 = {
               'route2' => {
                            'src' => [
                                     'dal'
                                    ],
                            'dst' => [
                                     'sfo'
                                    ]
                            }, 
               'route1' => {
                            'src' => [
                                     'bos'
                                    ],
                            'dst' => [
                                     'atl'
                                    ]
                            }
               };

如果我理解正确@routes是一个数组。 此数组的每个元素(route1,route2)都是一个哈希值。 此哈希的每个元素都是哈希。 此哈希的每个元素都是一个数组。

数组哈希的哈希数组。

如何循环获取@routes的元素。如果我遍历@routes,我应该得到route1和route2。在实际情况中,我不知道我的数组@routes中有多少“路由”。

2 个答案:

答案 0 :(得分:1)

@routes是一个数组。它包含一个元素,它是对哈希的引用。此哈希有两个键(route1route2),每个关联值是对哈希的另一个引用。内部哈希也各有两个键(srcdst)。关联的值是对数组的引用,每个数组都有一个元素,即一个字符串。

您无法在转储中看到外部数组结构,因为您有效地将@routes的内容列表传递给Dumper,而不是数组本身。并且数组只有一个元素,所以就好像你做了Dumper($routes[0])

以下代码未经测试但可能有效:

use strict;
use warnings;
use YAML qw(LoadFile);

my $routes = LoadFile('testcase');
my $n = keys %{$routes};
print "There are $n routes\n";

for my $k1 (keys %{$routes}) {
    print "$k1 =>\n";
    for my $k2 (keys %{$routes->{$k1}}) {
        print "    $k2 => @{$routes->{$k1}{$k2}}\n";
    }
}

答案 1 :(得分:1)

通过将LoadFile的返回值存储到数组中,您会使事情变得不必要地复杂化。 YAML允许在单个流中包含多个文档,因此理论上LoadFile可以返回多个引用。但事实上,您的流中只有一个文档,这是目前使用YAML的最常用方式

您应该将LoadFile的结果分配给单个标量,如下所示。请注意,我还使用了Data::Dump代替Data::Dumper;它不是核心模块(因此您可能需要安装它)但我认为它的输出更具可读性

use strict;
use warnings;

use YAML ();

open my $fh, '<', 'testcase.yaml' or die "Can't open YAML file: $!";

my $routes = YAML::LoadFile($fh);

use Data::Dump;
dd $routes;

输出

{
  route1 => { dst => ["atl"], src => ["bos"] },
  route2 => { dst => ["sfo"], src => ["dal"] },
}

现在我觉得结构很清楚

  • $routes是对哈希的引用,其中包含密钥route1route2

  • %$routes的每个值都是另一个哈希引用,键srcdst

  • srcdst对应的值是对数组的引用,每个数组只包含一个元素 - atlbos,{{ 1}},或sfo

所以你有一个哈希的数组哈希

处理哈希的方法有很多种,你选择哪种方法取决于你对信息的处理方式,但是你可以通过写

来遍历所有路径名。
dal

输出

for my $route ( keys %$routes ) {
    print "$route\n";
}

你可以说,像这样显示每条路线的来源和目的地

route2
route1

输出

for my $route ( keys %$routes ) {

    print "$route\n";

    my $sources = $routes->{$route}{src};
    my $destinations = $routes->{$route}{dst};

    print "  Sources:      @$sources\n";
    print "  Destinations: @$destinations\n";
    print "\n";
}