首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Perl的散列中包含散列

在Perl的散列中包含散列
EN

Stack Overflow用户
提问于 2011-01-24 12:29:37
回答 1查看 759关注 0票数 6

早上好,

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

例如,让我们看一些小的散列

文件personcontact.pl

代码语言:javascript
运行
复制
   return {
            \'firstname\' => {
                \'__type\' => \'String\'
            },
        \'lastname\' =>  {
            \'__type\' => \'String\'
            },
        %{include("/tmp/address.pl")}
    }

文件address.pl

代码语言:javascript
运行
复制
return {
        \'address\' => {
        \'street\' => {
            \'__type\' => \'String\'
            },
        \'unit\' => {
            \'__type\' => \'String\',
            \'__validation_function\' => {
                \'is_a_number\' => \'\'
            },
            \'__schema_constraints\' => {
                \'is_not_null\' => \'\'
            }
        },
        \'suburb\' => {
            \'__type\' => \'String\'
        },
        \'__type\' => \'ARRAY\'
        }
    } 

我有一大堆这样的东西。

我尝试重新创建散列的方法是使用include子例程,它看起来像这样:

代码语言:javascript
运行
复制
 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 6Odd number of elements in anonymous hash at (eval 11) line 5, <SCHEMAFILE> line 6这样的错误。我不确定如何找到(eval 11)第4-3行,第6行。任何关于使用Perl调试器的建议,或者任何关于我可能出错的地方的提示,都将不胜感激。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-24 14:14:08

欢迎使用Perl。我希望你有一个很好的学习和使用它的时间。

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

首先,通过评估文件来加载数据是不必要的。如果只想序列化数据,可以尝试使用JSON::XSYAML,甚至是Storable。如果您需要配置文件,CPAN上有很多模块可以帮助您完成此任务。查看Config::Any

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

既然已经解决了这个问题,如果您想要加载一个文件并对其进行评估(同样,这并不是几乎在所有情况下都是最好的想法),那么您应该考虑dorequire

代码语言:javascript
运行
复制
my $stuff = do 'address.pl';

但不要这么做。String eval是一种最好不使用的工具。99%的情况下,如果你打算使用string eval,停下来想一想其他的方法来解决这个问题。Do是一个隐式的eval,所以它也算数。

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

下一个话题,你到底想用那些漏掉的引语来达到什么目的?一看到那些东西我就头疼!Perl提供了some very, very nice quoting operators,您可以使用它来避免在文字字符串中使用转义引号。

=>或胖逗号自动引用其左侧(LHS),就好像它只是字母数字一样。但是,把所有的引号和转义放在一起会让事情变得很不可靠。

当您说\'address\' => {}时,Perl将其视为\,即应用于字符串文字的“获取引用”操作符。在本例中,是一个未终止的字符串文字,因为在第一个字符串文字之后从未提供过未转义的'

如果您的目标是使用'address'、quotes和all作为散列键,则可以这样做:

代码语言:javascript
运行
复制
my %foo = ( "'address'" => 'blah' );

如果你不想要引号,这似乎是一个更常见的用例,简单地这样做:

代码语言:javascript
运行
复制
my %foo = ( address => 'blah' );

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

现在,如果我要写这篇文章,我会这样做:

gen_schema_files.pl -用于编写JSON schema文件的文件。如果愿意,您可以手动编辑您的模式。如果您想提高可读性,您可能还希望将输出配置为更美观。

代码语言:javascript
运行
复制
#!/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 -这是加载模式并执行某些操作的代码。我的只装了子弹。我不知道你在用这些数据做什么。

代码语言:javascript
运行
复制
#!/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;
}

我已经对一些东西进行了润色,但我已经尝试在评论中留下足够多的术语(词汇甚至行话,如果你喜欢的话),让你可以进行有利可图的搜索。

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

Perldoc是一个令人惊叹的资源,但它的内容如此之多,以至于需要一段时间才能学会查找。看看Perl Data Structures CookbookArrays of Arrays tutorial。作为一个初学者,我发现Perl Functions by Category section of perlfunc非常有用。

既然我已经写了足够多的文字让一般人看不见了,我想我就停下来吧。我希望这篇论文对你有所帮助。再次欢迎您,晚上好(当您看到这条回复时,请调整到您当地的时间)。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4778649

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档