Gau*_*nia 6 perl hash perl-data-structures
天儿真好,
我正在努力从很多小哈希创造大哈希.假设这些较小的哈希值在每个文件中定义,然后可以包含在较大的哈希值中.
例如,让我们看一些小哈希
档案personcontact.pl:
return {
\'firstname\' => {
\'__type\' => \'String\'
},
\'lastname\' => {
\'__type\' => \'String\'
},
%{include("/tmp/address.pl")}
}
Run Code Online (Sandbox Code Playgroud)
档案address.pl:
return {
\'address\' => {
\'street\' => {
\'__type\' => \'String\'
},
\'unit\' => {
\'__type\' => \'String\',
\'__validation_function\' => {
\'is_a_number\' => \'\'
},
\'__schema_constraints\' => {
\'is_not_null\' => \'\'
}
},
\'suburb\' => {
\'__type\' => \'String\'
},
\'__type\' => \'ARRAY\'
}
}
Run Code Online (Sandbox Code Playgroud)
而且我有相当多的......
我试图重新创建哈希的方式是使用include子程序,如下所示:
sub include {
my ($filename) = @_;
my $file;
open(my $fh, "<", $filename) or die ("FILEOPEN: $!");
while(my $line = <$fh>) { $file .= $line; }
my $result = eval $file;
die("EVAL: $@") if $@;
close($fh) or die("FILECLOSE: $!");
return $result;
}
Run Code Online (Sandbox Code Playgroud)
我知道我一定做错了,但我不确定是什么.我继续得到像Useless use of a variable in void context at (eval 11) line 4, <SCHEMAFILE> line 6或的错误Odd number of elements in anonymous hash at (eval 11) line 5, <SCHEMAFILE> line 6.我不知道怎么去寻找(eval 11)第4-3行,第6行.任何有关使用Perl调试器的建议或任何关于我可能出错的指示都将非常感激.
谢谢!
dao*_*oad 11
欢迎来到Perl.我希望你有一个愉快的学习和使用它.
在商业上,从哪里开始?我在这里有很多话要说.
首先,通过评估文件来加载数据是不必要的风险.如果您只想序列化数据,请尝试使用JSON :: XS或YAML,甚至是Storable.如果您需要配置文件,CPAN上有许多模块可以帮助完成此任务.查看Config :: Any.
如果你想创建通过eval加载的数据结构(这不是一个好主意),Data :: Dumper会生成创建你提供给它的任何数据结构所需的perl代码.我提到它的主要原因是它作为调试辅助工具比串行器更有用.
现在,这是照顾的,如果要加载一个文件,并评估它(同样,没有最好在几乎所有情况下的想法),你应该寻找在做或需要.
my $stuff = do 'address.pl';
Run Code Online (Sandbox Code Playgroud)
但是不要这样做.字符串eval是一种通常最好不使用的工具.99%的情况下,如果您计划使用字符串评估,请停止并考虑另一种方法来解决问题.Do是一个隐含的eval,所以它也很重要.
Perl为您提供了许多工具来进行冒险和强大的魔法.成为熟练的Perl编程的很大一部分在于理解什么是有风险的东西,为什么以及何时使用它们是有意义的.不要指望Perl用栅栏和大门来保护你,以保证你的安全.认真考虑选择有效Perl编程或Perl最佳实践的副本.作为一个新手,当你第一次阅读时,很多东西会超过你的头脑,但是随着你的成长和学习,这两本书都可以作为一个很好的参考.
下一个主题,您想要通过所有那些转义报价实现什么?看着那些东西让我头疼!Perl有一些非常非常好的引用运算符,您可以使用它们来避免在文字字符串中转义引号.
该=>或脂肪逗号自动报价的左侧(LHS),就好像它是唯一的字母数字.但是把所有的引用和逃脱都让事情变得非常狡猾.
当你说\'address\' => {},Perl将此视为\应用于字符串文字的"get reference"运算符.在这种情况下,一个未终止的字符串文字,因为你从未'在第一个之后提供未转义的字符串.
如果你的目标是使用'address',引号和all作为你的哈希键,你可以这样做:
my %foo = ( "'address'" => 'blah' );
Run Code Online (Sandbox Code Playgroud)
如果你不想要引号,这似乎是一个更常见的用例,只需:
my %foo = ( address => 'blah' );
Run Code Online (Sandbox Code Playgroud)
关于你得到的错误消息!一旦你了解了它们的意思,Perl就会有一些非常好的错误消息.在那之前,理解它们的重要性可能有点困难.幸运的是,Perl附带了一个名为的脚本splain:一个方便的花花公子工具,可以更详细地解释错误消息.您还可以使用诊断模块自动获取相同的扩展错误消息.
现在,如果我写这篇文章,我会按照以下方式做点什么:
gen_schema_files.pl - 用于编写JSON模式文件的文件.如果您愿意,可以手动编辑您的模式.如果要提高可读性,可能还需要将输出配置为更漂亮.
#!/usr/bin/perl
use JSON::XS;
use File::Spec;
use constant BASEDIR => '.';
# Key is the file name, value is the data to put into the file.
my %schemata = (
'address.json' => {
address => {
street => { __type => 'String' },
unit => {
__type => 'String',
__validation_function => { is_a_number => '' },
__schema_constraints => { is_not_null => '' }
},
suburb => { __type => 'String' },
__type => 'ARRAY'
},
},
'person_contact.json' => {
firstname => { __type => 'String' },
lastname => { __type => 'String' },
# Use a special key to indicate that additional files should be
# loaded into this hash.
INCLUDE => [qw( address.json )],
},
# And so forth
);
for my $schema ( keys %schemata ) {
my $path = File::Spec->catfile( BASEDIR, $schema );
open my $fh, '>', $path
or die "Error opening '$path' for writing - $!\n";
print $fh encode_json $schemata{$schema};
}
Run Code Online (Sandbox Code Playgroud)
load_schemas.pl - 这是加载模式并执行操作的代码.我只会装满.我不知道你在做什么数据......
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use JSON::XS;
use File::Spec;
use constant BASEDIR => '.';
my $schema = load_schema( 'person_contact.json' );
print Dumper $schema;
sub load_schema {
my $file = shift;
my $path = File::Spec->catfile( BASEDIR, $file );
open my $fh, '<', $path
or die "Error opening file '$path' - $!\n";
my $json = join '', <$fh>; # reads a list of lines and cats them into one string.
# One way to slurp out of many.
my $schema = decode_json( $json );
# Handle the inclusion stuff:
if( exists $schema->{INCLUDE} ) {
# Copy the files to load into an array.
my @loadme = @{$schema->{INCLUDE}};
# delete the magic special include key.
delete $schema->{INCLUDE};
# Load each file and copy it into the schema hash.
for my $load ( @loadme ) {
my $loaded = load_schema( $load );
# This is a bit of weird syntax.
# We are using a hash slice assignment to copy the loaded data into the existing hash.
# keys and values are guaranteed to come out in the same (random) order as each other.
# the @{$foo}{blahbhal} is how you dereference a hash reference as a slice.
@{$schema}{keys %$loaded} = values %$loaded;
}
}
return $schema;
}
Run Code Online (Sandbox Code Playgroud)
我已经掩盖了一些事情,但我试图用足够的术语(词汇或甚至行话,如果你愿意)留下评论,以允许你做有利可图的搜索.
上面的代码有几个缺陷.它不会检查圆形内含物(它会运行很长时间并最终填满内存并崩溃 - 不太好).魔术键的选择可能不太好.而且我可能还有更多想法.
Perldoc是一个令人惊叹的资源,但有很多东西需要一段时间来学习找东西.看一下Perl Data Structures Cookbook和Arrays of Arrays教程.作为初学者,我发现perlfunc的Perl Functions by Category部分非常有用.
我想我会停下来,因为我已经写了足够的文字来瞎了普通人.我希望你发现这篇论文很有帮助.欢迎,再次,晚上好(请根据当地时间调整,以便找到此回复).