我必须解析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中有多少“路由”。
答案 0 :(得分:1)
@routes
是一个数组。它包含一个元素,它是对哈希的引用。此哈希有两个键(route1
,route2
),每个关联值是对哈希的另一个引用。内部哈希也各有两个键(src
,dst
)。关联的值是对数组的引用,每个数组都有一个元素,即一个字符串。
您无法在转储中看到外部数组结构,因为您有效地将@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
是对哈希的引用,其中包含密钥route1
和route2
%$routes
的每个值都是另一个哈希引用,键src
和dst
与src
和dst
对应的值是对数组的引用,每个数组只包含一个元素 - atl
,bos
,{{ 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";
}