3

Data :: Dumperを使用して、Perlでデータを文字列にシリアル化しました。今、別のプログラムで、を使用して逆シリアル化しようとしていますが、次のevalようになります。

Global symbol "$VAR1" requires explicit package name

私はuse warnings; use strict;自分のプログラムで使用しています。

これが私evalがコードをどのように使っているかです:

my $wiki_categories = eval($db_row->{categories});
die $@ if $@;
/* use $wiki_categories */

"$VAR1"として宣言されていないために死にかけているプログラムを無効にするにはどうすればよいmyですか?

"my "の前に追加する必要が$db_row->{categories}ありevalますか?このような:

my $wiki_categories = eval("my ".$db_row->{categories});

私はまだこれをテストしていませんが、うまくいくと思います。

これを行う他の方法はありますか?おそらくそれをいくつかのブロックでラップし、そのブロックに対してstrictをオフにしますか?私はそれをしたことがありませんが、それが言及されているのを見ました。

助けていただければ幸いです。

4

3 に答える 3

8

これは正常です。デフォルトでは、Data :: Dumperがデータをシリアル化すると、次のように出力されます。

$VAR1 = ...your data...

シリアル化にData::Dumperを使用するには、少し構成する必要があります。 設定する最も重要なオプションであり、それは物事Terseをオフにします。$VAR

use Data::Dumper;

my $data = {
    foo => 23,
    bar => [qw(1 2 3)]
};

my $dumper = Data::Dumper->new([]);
$dumper->Terse(1);

$dumper->Values([$data]);
print $dumper->Dump;

次に、結果を変数に直接評価できます。

my $data = eval $your_dump;

Data :: Dumperのサイズを縮小するためにさまざまなトリックを実行できますが、全体としては高速でスペース効率が高くなります。主な欠点は、Perlのみであり、非常に安全でないことです。誰かがあなたのダンプファイルを変更できるなら、彼らはあなたのプログラムを所有しています。

CPANには、これを処理するモジュールがあり、Data::Serializerなどのモジュールがあります。

于 2012-06-21T19:13:30.727 に答える
6

あなたの質問には多くの意味があります。できるだけ多くのことを取り上げようと思います。

まず、Data::Dumperのperldocを読みます。設定$Data::Dumper::Terse = 1はあなたのニーズに十分かもしれません。ここでグローバル変数には多くのオプションがあるので、必ずそれらをローカライズしてください。ただし、これにより、データのコンシューマーではなくプロデューサーが変更されます。あなたがそれをどれだけコントロールできるかわかりません。あなたの質問は、あなたが消費者に取り組んでいることを意味しますが、生産者に対するいかなる管理についても言及していません。たぶん、データはすでに存在しているので、そのまま使用する必要があります。

次の意味は、Data::Dumperに縛られているということです。繰り返しになりますが、データはすでに存在している可能性があるため、残念ながらそれを使用してください。そうでない場合は、別の保存可能な形式に切り替えることをお勧めします。最近のかなり一般的なものはJSONです。JSONはコアperlの一部ではありませんが、インストールするのは非常に簡単です。また、これがはるかに簡単になります。1つの利点は、データが他の言語でも役立つことです。もう1つは、データが危険にさらされた場合に消費者を簡単に危険にさらす可能性のあるevalSTRINGを回避することです。

次の項目は、それをそのまま解決する方法です。たとえば、データが存在する場合。簡単な解決策は、あなたがしたようにmyを追加することです。これは正常に機能します。もう1つは、$VAR1を削除することです(my $dumped = $db_row->{categories}) =~ s/^\s*\$\w+\s*=\s*//;。もう1つは、「警告なし」を評価に正しく入れることですeval ("no warnings; no strict; " . $db_row->{categories});

個人的には、可能な限りJSONを使用します。

于 2012-06-21T19:15:57.407 に答える
2

のスコープで宣言されておらず、有効であるevalために失敗することを除いて、コードはそのままの状態で機能します。$VAR1evaluse strict 'vars'

可能な限りタイトなブロック内の狭窄を無効にすることで、これを回避します。ブロックはこのdoようにトリックを行います

my $wiki_categories = do {
  no strict 'vars';
  eval $db_row->{categories};
};
于 2012-06-21T19:49:34.787 に答える