http://qs321.pair.com?node_id=11116141

nysus has asked for the wisdom of the Perl Monks concerning the following question:

I dumped a hash into a file and then copied into the __DATA__section of my script. $Data::Dumper::Purity = 1; was set prior to outputting to file:
use strict; use warnings; use Data::Dumper qw(Dumper); my $hash; { local $/; $hash = <DATA>; } $hash = eval { $hash }; print keys %$hash; # error __DATA__ $VAR1 = { 'blah.com' => [ '212.235.56.176' ], 'blah.org' => [ '212.235.56.176' ], 'www.boo.org' => [ '212.235.56.176' ], };

I tried getting rid of $VAR1 in __DATA__ but that didn't help.

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: unable to eval dumped hash
by kcott (Archbishop) on Apr 28, 2020 at 08:01 UTC

    G'day nysus,

    Writing the Dumper output to a file, manually opening that file, manually copying its contents, then manually pasting into a script, does not seem like a very sensible way to go. Even if you're using less manual steps — e.g. 'cat dumper.out >> script.pl' or 'G:r dumper.out' from 'vim script.pl' — I still wouldn't recommend it. You should not have to edit your code every time the data changes. Consider reading the Dumper output directly in your script.

    "I tried getting rid of $VAR1 ..."

    Perhaps Data::Dump would be a better choice:

    $ perl -e ' use Data::Dumper; use Data::Dump; my $x = { a => 1, b => [1,2,3] }; print "*** From Data::Dumper ***\n"; print Dumper $x; print "*** From Data::Dump ***\n"; dd $x; ' *** From Data::Dumper *** $VAR1 = { 'b' => [ 1, 2, 3 ], 'a' => 1 }; *** From Data::Dump *** { a => 1, b => [1, 2, 3] }

    Also take a look at Storable, JSON and YAML (those last two also have XS versions which will be faster).

    — Ken

      Thanks, yes, I'm aware. My code is more or less an experiment on how to use the __DATA__ feature with dumped data. The data I dumped took several minutes to generate so I didn't really feel like re-running the code that generated it in the first place. Figured I'd try a "shortcut" which took longer than re-rerunning the code. But hey, I learned something.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: unable to eval dumped hash
by bliako (Monsignor) on Apr 28, 2020 at 08:14 UTC

    To get rid of $VAR1 I set $Data::Dumper::Terse = 1; (also relevant $Data::Dumper::Varname).

    The idiom I use for eval'ing is:

    my $result = eval { $hash }; if( $@ || ! $result ){ die "error eval: $@" }

    For "undumping" there is also Data::Undump which claims to be secure, I guess that's in reference to the eval? But it's not clear to me.

      There is also the Safe module for evaluating untrusted input while limiting possible damage.

Re: unable to eval dumped hash
by nysus (Parson) on Apr 28, 2020 at 00:44 UTC

    OK, noodled with this some more. This worked:

    use Data::Dumper qw(Dumper); use warnings; use strict; my $hash; { local $/; $hash = <DATA>; } my $VAR1; eval $hash; print keys %$VAR1; __DATA__ $VAR1 = { 'blah.com' => [ '212.235.56.176' ], 'blah.org' => [ '212.235.56.176' ], 'www.boo.org' => [ '212.235.56.176' ], };

    Originally, I was using eval like I was running a block of code, but that's not what I wanted.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

Re: unable to eval dumped hash
by BillKSmith (Monsignor) on Apr 28, 2020 at 14:48 UTC
    You have already discovered that you need the EXPR (not BLOCK) form of eval. With this change, your original idea of removing $VAR1 works fine.
    use strict; use warnings; use Data::Dumper qw(Dumper); my $hash; { local $/; $hash = <DATA>; } #$hash = eval { $hash }; $hash = eval $hash ; print keys %$hash; # error (no more) __DATA__ #$VAR1 = { { 'blah.com' => [ '212.235.56.176' ], 'blah.org' => [ '212.235.56.176' ], 'www.boo.org' => [ '212.235.56.176' ], };

    OUTPUT:

    C:\Users\Bill\forums\monks>perl 11116141.pl blah.comblah.orgwww.boo.org
    Bill
Re: unable to eval dumped hash
by Anonymous Monk on Apr 28, 2020 at 00:20 UTC
    what does $@ say?

    { blah.com' => [ doesnt look right

      I accidentally deleted the apostrophe. It's fixed.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Re: unable to eval dumped hash
by haukex (Archbishop) on May 02, 2020 at 09:54 UTC

    Shameless plug: You might be interested in my module Data::Undump::PPI. It uses a static parse so it's safer than eval.

    I dumped a hash into a file and then copied into the __DATA__section of my script.

    Although I wouldn't recommend this for real-world use (use a config file instead), see my reply in the thread Is it possible to modify __DATA__ via the DATA file handle or otherwise? for a script that modifies its own __DATA__ section:

    use warnings; use strict; use File::Replace 'replace3'; use Data::Undump::PPI qw/Dump Undump/; my $pos = tell DATA; my $data = Undump(fh => *DATA); $data->{counter}++; my (undef,$outfh,$repl) = replace3(__FILE__,':raw'); $repl->copy($pos); Dump([$data], fh=>$outfh); $repl->finish; __DATA__ $VAR1 = { counter => 0 };