2011-01-24 23 views
6

G'Day、ハッシュをPerlに含める

私は現在、多くの小さなハッシュから大きなハッシュを作成しています。これらのより小さいハッシュがそれぞれファイル内で定義され、より大きなハッシュに含めることができるとしましょう。

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

ファイルaddress.pl

などのために、のいくつかの小さなハッシュ

ファイルpersoncontact.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: [email protected]") if [email protected]; 
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のデバッガやポインタの使用に関する示唆は高く評価されます。

ありがとうございます!

+2

1行ずつ読む必要はありません。ファイルを読む前に 'local $ /;'を入れて "slurp mode"を使い、while(my $ line ...)を 'my $ line = <$fh>;'に変更してください。 – Mikel

+0

チップをありがとう!あなたが推測したように、私はかなりPerlを新しくしています:) –

+3

YAMLのようなものがもっと適切かもしれません。 http://search.cpan.org/dist/YAML/lib/YAML.pm – Mikel

答えて

11

ようこそ。私はあなたが楽しく学び、それを使用していることを願っています。

オンデマンドで、どこから始めるのですか?私はここでたくさん言い聞かせている。

最初に、ファイルを評価してデータを読み込むことは不必要に危険です。データをシリアル化する場合は、JSON::XSまたはYAML、さらにはStorableを試してください。設定ファイルが必要な場合は、このタスクに役立つ多くのモジュールがCPAN上にあります。チェックアウト:Config::Any

eval経由でロードするデータ構造を作成する場合(実際には良いことではありません)、Data::Dumperは、データ構造を作成するために必要なperlコードを生成します。私が言及した主な理由は、シリアライザよりもはるかにデバッグの助けとして役立つということです。

今、あなたは(ほぼすべてのケースで最高のアイデア、再びない)ファイルをロードし、それを評価する場合ことは、の世話をしていることを、あなたはdoまたはrequireされているはずです。

my $stuff = do 'address.pl'; 

しかし、そうしないでください。文字列evalは、一般的には未使用のまま残されたツールです。あなたが文字列evalを使用することを計画しているなら、時間の99%を停止し、問題を解決する別の方法を考える。 Doは暗黙の評価であるため、それも重要です。

Perlは、危険で強力な魔法を行うツールをたくさん提供します。熟練したPerlのプログラミングになる大きな部分は、危険なものが何であるか、なぜ、それを使うのが理にかなっているのかを理解することにあります。あなたを安全に保つために、フェンスとゲートであなたに赤ちゃんにPerlを期待しないでください。真剣に、Effective Perl ProgrammingまたはPerl 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; 
} 

私はいくつかの上に練りましたが、私は用語(語彙、あるいは専門用語を十分にコメントを残すことを試みた、場合あなたは有益な検索を行うことができます)。

上記コードにはいくつかの欠陥があります。円形のインクルージョンをチェックすることはありません(長い間実行され、最終的にはメモリとクラッシュを埋める - それほど良いことではありません)。魔法の鍵の選択は良いではないかもしれません。そして、おそらくもっと私はまだ考えていない。

Perldocは驚くほどのリソースですが、そこには物事を見つけることを学ぶのにしばらく時間がかかります。 Perl Data Structures CookbookArrays of Arrays tutorialを見てください。初心者として、私はPerl Functions by Category section of perlfuncが非常に有用であることを発見しました。

平均的な人を盲目的にするのに十分な文章を書いたので、私はやめます。私はあなたがこの論文を参考にしてくれることを願っています。ようこそ、もう一度、おはようございます(あなたの現地時間に調整してください)。

関連する問題