gpt4 book ai didi

perl - 在 Perl 中的散列中包含散列

转载 作者:行者123 更新时间:2023-12-04 13:55:00 27 4
gpt4 key购买 nike

G'Day,

我目前正致力于从许多较小的散列中创建大散列。假设这些较小的散列分别定义在一个文件中,然后可以包含在较大的散列中。

例如,让我们看看一些小的哈希值

文件 personcontact.pl :

   return {
\'firstname\' => {
\'__type\' => \'String\'
},
\'lastname\' => {
\'__type\' => \'String\'
},
%{include("/tmp/address.pl")}
}

文件 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\'
}
}

我有相当多的这些......

我尝试重新创建哈希的方法是使用 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;
}

我知道我一定做错了什么,但我不确定是什么。我不断收到类似 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 调试器的建议或任何关于我可能出错的地方的指示都将不胜感激。

谢谢!

最佳答案

欢迎使用 Perl。我希望你有一个愉快的学习和使用它。

做生意,从哪里开始?我在这里有很多话要说。

首先,通过评估文件加载数据存在不必要的风险。如果您只想序列化数据,请尝试 JSON::XSYAML ,甚至 Storable .如果你想要一个配置文件,CPAN 上有很多模块可以帮助完成这个任务。退房 Config::Any .

如果你想创建数据结构以通过 eval 加载(这不是一个好主意),Data::Dumper生成创建您提供给它的任何数据结构所需的 perl 代码。我提到它的主要原因是它作为调试辅助工具比序列化程序更有用。

既然已经解决了这个问题,如果你想加载一个文件并对其进行评估(同样,在几乎所有情况下都不是最好的主意),你应该查看 dorequire .

my $stuff = do 'address.pl';

但不要那样做。字符串 eval 是一种通常最好不要使用的工具。 99% 的情况下,如果您打算使用字符串 eval,请停下来想其他方法来解决问题。 Do 是一个隐式的 eval,所以它也很重要。

Perl 为您提供了许多工具来实现危险而强大的魔法。成为熟练的 Perl 编程人员的很大一部分在于了解哪些事情是有风险的,为什么以及何时使用它们是有意义的。不要指望 Perl 会用栅栏和门来保护你的安全。认真考虑拿一份 Effective Perl ProgrammingPerl Best Practices .作为一个新手,当你第一次阅读时,你会想很多,但随着你的成长和学习,这两本书都可以成为很好的引用。

下一个主题,你到底想用所有这些转义的引号实现什么?看着那些东西,我的头很痛! Perl 有 some very, very nice quoting operators您可以使用它来避免在文字字符串中转义引号。
=>或胖逗号自动引用其左侧(LHS),就好像它只是字母数字一样。但是把所有的引号和转义符都放在一起会让事情变得很狡猾。

当你说 \'address\' => {} , Perl 将其视为 \ ,应用于字符串文字的“获取引用”运算符。在这种情况下,是未终止的字符串文字,因为您从不提供未转义的 '第一次之后。

如果您的目标是使用 'address' ,引号和所有作为您的哈希键,您可以这样做:
my %foo = ( "'address'" => 'blah' );

如果您不想要引号,这似乎是一个更常见的用例,只需执行以下操作:
my %foo = ( address => 'blah' );

转到您收到的错误消息!一旦你了解了它们的全部含义,Perl 就会有一些非常好的错误消息。在那之前,要理解它们的重要性可能有点困难。幸运的是,Perl 附带了一个名为 splain 的脚本。 :一个方便的花花公子工具,它将更详细地解释错误消息。您也可以使用 diagnostics模块以自动获取相同的扩展错误消息。

现在,如果我正在写这篇文章,我会按照以下方式做一些事情:

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};
}

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;
}

我已经掩盖了一些事情,但我试图用足够的术语(词汇甚至行话,如果你喜欢)留下评论,让你进行有利可图的搜索。

上面的代码有几个缺陷。它不会对循环包含进行任何检查(它会运行很长时间并最终填满内存并崩溃 - 不太好)。魔法 key 的选择可能不太好。可能还有更多我还没有想到的。

Perldoc 是一个了不起的资源,但是那里的资源太多了,需要花一些时间才能学会找到东西。看看 Perl Data Structures CookbookArrays of Arrays tutorial .作为初学者,我发现了 Perl Functions by Category section of perlfunc非常有帮助。

我想我会停下来,既然我已经写了足够多的文字来使普通人失明。我希望你觉得这篇论文有帮助。再次欢迎您,晚上好(当您找到此回复时,请根据您本地的时间进行调整)。

关于perl - 在 Perl 中的散列中包含散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4778649/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com