通常,perl对象是数据结构,例如散列,数组,标量,文件句柄等。
我在想一个perl模块可以将对象的哈希值(每个对象作为哈希值)作为单个对象返回的场景。请考虑以下情况。
我有一个包含多个文档的YAML文件。 (或具有多组相同配置节点的XML)。我需要一个perl模块,我可以将此YAML文件作为输入传递,并接收对象的散列(每个对象对应于YAML文件中的文档)。
YAML
---
mykey: 1
myname: John
---
mykey: 2
myname: Doe
----
mykey: 3
myname: Chris
...
上面的YAML文件中有3个文件。让我们考虑一下这将是输入文件。
我想写下面的内容并访问对象的哈希值。
SimpleParser.pl
use strict;
use warnings;
use YAMLParser;
my %objHashRef = YAMLParser->new('input.yml');
print keys %objHashRef; #print keys for each objects
print values %objHashRef; #print hash reference of each object
my $thirdObjectName = $objHashRef{3}->get_name();
print $thirdObjectName; #this prints 'Chris'
要实现此行为,perl模块文件中所需的所有修改都与下面的内容类似?
YAMLParser.pm
use strict;
use warnings;
sub new {
my ($class) = shift;
my $self = {
inputFile => shift,
name => shift
};
bless $self, $class;
return $self;
}
sub set_name {
$self->{name} = $name;
}
sub get_name {
my ($self) = @_;
return $self->{name};
}
1;
以下是一个示例YAML解析代码段,如果需要可以提供帮助。
my @list;
my $myname;
my $i = 0;
my @conf = LoadFile('input.yml'); #returns array of reference to each document in the YAML file
my $config = \@conf; #Returns reference to an array
foreach ( @conf ) {
$list[$i] = $config->[$i]->{mykey};
$objHash{$list[$i]} = YAMLParser->new();
$myname = $config->[$i]->{myname};
$objHash{$list[$i]}->setMyname($myname);
my $host = $objHash{$list[$i]}->getMyname();
$i++;
}
请让我知道你的想法。
答案 0 :(得分:2)
只需将结构存储到由mykey
键入的哈希值中。我使用map,但也可以使用for循环:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
{
package YAMLHash;
use YAML qw{ LoadFile };
sub new {
my ($class, $file) = @_;
my %hash = map { $_->{mykey} => $_ } LoadFile($file);
bless \%hash, $class
}
}
my $obj = 'YAMLHash'->new('1.yaml');
say keys %$obj;
say values %$obj;
my $third_object_name = $obj->{3}{myname};
print $third_object_name; #this prints 'Chris'
请注意$obj->{3}
不是第三个对象。它是mykey
为3的对象。
答案 1 :(得分:0)
CPAN上有很多模块可以很好地用哈希创建一个对象(哎呀,我甚至写了一个:Hash::Wrap)。如果您想以递归方式将对象范例应用于YAML文档的嵌套部分,我最喜欢的是Hash::AsObject。有关类似模块的更全面列表,请参阅Hash::Wrap。
这里有一些代码。它返回对象的列表,而不是对象的 hash ,但修复它非常简单。
use 5.010;
use strict;
use warnings;
use Hash::AsObject;
use YAML 'Load';
my $yaml = do { local $/ = undef;
<DATA>
};
my @objs = map { Hash::AsObject->new( $_ ) } Load( $yaml );
say " Name: ", $objs[0]->myname;
$objs[0]->myname( "Frank" );
say " Name: ", $objs[0]->myname;
__DATA__
---
mykey: 1
myname: John
---
mykey: 2
myname: Doe
---
mykey: 3
myname: Chris
输出:
Name: John
Name::Frank