我正在尝试从我的perl脚本的YAML文件中获取数据。
以下是类似的示例场景:
让我们考虑员工数据的YAML文件。
---
emp_name: John
emp_age: 27
DOB: 1/1/1990
others:
- key1: value1
- key2: value2
---
emp_name: Doe
emp_age: 25
DOB: 1/1/1992
others:
- key1: value1
- key2: value2
---
emp_name: foo
emp_age: 22
DOB: 1/1/1995
others:
- key1: value1
- key2: value2
---
emp_name: Bar
emp_age: 21
DOB: 1/1/1996
others:
- key1: value1
- key2: value2
...
我有以上四组值。我试图将所有员工姓名保存在一个数组中。但我无法得到它。
使用dumper,我只能将第一部分(John's)文件作为JSON打印,我无法获得单个值(例如,获取数组中的所有员工姓名)。 / p>
use strict;
use warnings;
use YAML::XS 'LoadFile';
use Data::Dumper;
my $config = LoadFile('input2.yml');
print Dumper($config), '\n';
print "Expected output:\n";
print "John \nDoe \nfoo \nBar\n";
print "--- Actual Output --";
my $empName;
for(my $i=0; $i<4; $i++)
{
$empName = $config->[$i]->{emp_name};
}
任何帮助?
以上是代码。我想获取员工姓名列表,但收到错误:Not an ARRAY reference at yamlParser.pl line 15
答案 0 :(得分:2)
与JSON不同,YAML可能包含多个文档。它们中的每一个都以数据流中的---
开头,最后一个文档的末尾由...
您使用的YAML数据包含四个此类文档,这些文档由LoadFile
作为引用列表返回。如果将该列表分配给标量变量,那么它将获取最后一个元素,因此您需要将结果放入数组(或标量变量列表)
此代码将按您的要求执行。它将YAML数据检索到数组@config
,然后使用map
提取每个哈希的emp_name
元素
use strict;
use warnings 'all';
use feature 'say';
use YAML::XS 'LoadFile';
my @config = LoadFile 'input2.yml';
my @names = map { $_->{emp_name} } @config;
say for @names;
John
Doe
foo
Bar
答案 1 :(得分:1)
提供的yaml提供4个文档,而不是4个项目的数组,因此您只需要取消引用它们。阅读文档: perldoc YAML::XS
变化:
my $config = LoadFile('input2.yml');
致:
my @conf = LoadFile('input2.yml');
my $config = \@conf;
答案 2 :(得分:-1)
让我们首先考虑一些关于YAML的基本知识,而不是文件本身。
包含 YAML流的文件可以包含多个完整不同数据结构的无关 YAML文档,由---
分隔。
您的文件似乎包含相同结构的记录,您可能只需要一个文档,其中包含记录的 YAML序列 记录为 YAML映射。
以下是你应该拥有的:
- emp_name: John
emp_age: 27
DOB: 1/1/1990
others:
key1: value1
key2: value2
- emp_name: Doe
emp_age: 25
DOB: 1/1/1992
others:
key1: value1
key2: value2
- emp_name: foo
emp_age: 22
DOB: 1/1/1995
others:
key1: value1
key2: value2
- emp_name: Bar
emp_age: 21
DOB: 1/1/1996
others:
key1: value1
key2: value2
注意区别; 1份文件;每条记录都以包含-
的行开头; others
现在是一个真正的映射,而不是单个映射的序列(- key: value
,已移除-
)
现在,以下代码将文件的内容读入单个变量,该变量将ArrayRef保存到单个YAML文档的整个数据结构。
use strict;
use warnings;
use YAML;
my $data = YAML::LoadFile('input2_correct.yml');
use Data::Dumper;
print Dumper $data;
仅供参考:在列表上下文中使用YAML::LoadFile
会读取所有单独的文档。
请修复您的YAML文件!
从现在开始,如果需要,可以轻松地使用map
来操作散列中的Perl数据结构,或者打印名称:
print "$_->{emp_name}\n" foreach @$data;
或者,如果你想打印所有'Doe'记录的年龄......
my $name = 'Doe';
foreach my $emp_record ( @$data ) {
next unless $emp_record->{emp_name} eq $name;
# do what you like to do with the record
print "$emp_record->{emp_age}\n";
}
如果只有1个记录'Doe',下面的代码将打印第一个'Doe'的年龄:
my ($found) = grep { $_->{emp_name} eq $name } @$data;
print "$found->{emp_age}\n";
grep
会将列表缩减为仅在给定表达式中评估为true的列表。 my (found)
导致grep的列表上下文,并将被分配缩小列表的第一个