1

Perl でシリアライズとデシリアライズを行う必要があります。Data::Dumperと がこの仕事に最適ではないことは承知していevalますが、私が取り組んでいるレガシー スクリプトでこの側面を変更することは許可されていません。
以下に 2 つの使用方法 ( CODE 1CODE 2 ) を示しますevalCODE 1
では、ハッシュは を介し​​て逆シリアル化される前に文字列として使用できます。CODE 2 では、ハッシュは を使用してシリアライズされてから、 を介してデシリアライズされます。 eval
Dumpereval

どちらのコード サンプルでも、逆シリアル化を試みる 2 つの方法のうちの 1 つが機能します。逆シリアル化する他の方法が機能しないのはなぜですか?

コード 1

my $r2 = "( 
'w' => {
           'k2' => 5,
           'k1' => 'key',
           'k3' => [
                     'a',
                     'b',
                     2,
                     '3'
                   ]
         },
  'q' => 2 
)"; 

my %z; 
eval "\%z = $r2";          ####### Works. 
print "\%z = [".Data::Dumper::Dumper (\%z)."] "; 

my $answer = eval "$r2";   #### Does NOT work. 
print "\n\nEvaled = [".Dumper($answer)."] "; 

出力

%z = [$VAR1 = {
          'w' => {
                   'k2' => 5,
                   'k1' => 'key',
                   'k3' => [
                             'a',
                             'b',
                             2,
                             '3'
                           ]
                 },
          'q' => 2
        };
]

Evaled = [$VAR1 = 2;
]

ただし、以下のコードは逆の方法で機能します:
CODE 2

my %a = ( "q" =>2, "w"=>{ "k1"=>"key", "k2"=>5, k3=>["a", "b", 2, "3",], }, );  **# Same hash as above example.** 
$Data::Dumper::Terse=1; 
$Data::Dumper::Purity = 1; 
my $r2 = Dumper(\%a); 

my %z; 
eval '\%z = $r2'; 
print "\n\n\%z = [".Dumper(\%z)."] ";         #### Does NOT work. 

my $answer = eval $r2; 
print "\n\nEvaled = [".Dumper($answer)."] ";  ####### Works.

出力

%z = [$VAR1 = {};
]

Evaled = [$VAR1 = {
          'w' => {
                   'k2' => 5,
                   'k1' => 'key',
                   'k3' => [
                             'a',
                             'b',
                             2,
                             '3'
                           ]
                 },
          'q' => 2
        };
]
4

2 に答える 2

2

まず、構文エラーになるようなコメントは入れないでください ( **)。

最初のコード ブロックで指定した文字列は、Dumper 関数とは異なるデータ構造を生成することに注意してください。最初のブロックではハッシュを作成していますが、それをどの変数にも割り当てていません。Dumper 関数の場合、匿名ハッシュが作成され、その参照が$VAR変数に渡されます。

最初のコードを機能させるには、次のように置き換え({匿名ハッシュを作成し、それを変数に割り当てる必要があります。

my $r2 = "$VAR = { 
    'w' => {
           'k2' => 5,
           'k1' => 'key',
           'k3' => [
                     'a',
                     'b',
                     2,
                     '3'
                   ]
         },
  'q' => 2 
}"; 
于 2016-03-28T11:51:13.683 に答える
1

Data::Dumper を使用してデータをシリアル化しないでください。そうは言っても...

これは、スカラーおよびリスト コンテキストの問題です。2 番目の評価では、次のようになります。

my $answer = ...;

スカラーに割り当てているため、右側はスカラー コンテキストで評価されます。これは、evalがスカラー コンテキストにあることを意味します。その値は次のとおりです。

(
'w' => {
           'k2' => 5,
           'k1' => 'key',
           'k3' => [
                     'a',
                     'b',
                     2,
                     '3'
                   ]
         },
  'q' => 2
)

これはリストのように見えますが、実際にはスカラー コンテキストのカンマ演算子です。これは左辺を評価し、その結果を破棄して、右辺を返します。したがって、 にmy $x = ( 'left', 'right' )割り当てrightます$x。これについては、リストと配列の違いは何ですか? で説明されています。perlfaq4で。

あなたの質問では、それ$rが値を取得することがわかります2。これはコンマ チェーンの右端の値なので、スカラー コンテキストで返される値です。それを別の値 (おそらく'duck') に変更すると、その値が返されます。

my $r2 = "(
    'w' => {
               'k2' => 5,
             },
      'q' => 'duck'
    )";

my $answer = eval "$r2";

use Data::Dumper;
print "Evaled =\n" . Dumper($answer);

これは数字ではありません。これはある種の数だと考えているため、人々を混乱させます。

Evaled =
$VAR1 = 'duck';

リストコンテキストで割り当てるように変更すると(ハッシュ割り当てはリスト割り当てです)、正しい答えが得られます。

my $r2 = "(
    'w' => {
               'k2' => 5,
             },
      'q' => 'duck'
    )";

my @answer = eval "$r2";

use Data::Dumper;
print "Evaled =\n" . Dumper(\@answer);

これで、あるべきだと思ったデータ構造になりました。

Evaled =
$VAR1 = [
          'w',
          {
            'k2' => 5
          },
          'q',
          'duck'
        ];
于 2016-03-28T19:31:17.943 に答える