We often need to dump data in Perl. The standard library has Data::Dumper and Dumpvalue, but when I have good access to CPAN, I prefer to use Data::Dump or YAML. Last year, I heard about Data::Printer and used that for a while, but switched back to Data::Dump because I couldn't distinguish between a blank string and a string with just nulls in it. If I had data that looked like
my $stuff = {
blank => "",
null => "\0",
undefined => undef,
zed => 0,
zero => '0',
};
Data::Printer gave me
\ {
blank "",
null "",
undefined undef,
zed 0,
zero 0
}
whereas Data::Dump gave
{ blank => "", null => "\0", undefined => undef, zed => 0, zero => 0 }
and YAML gave
---
blank: ''
null: "\0"
undefined: ~
zed: 0
zero: 0
Yes, the Data::Printer output is very colorful, but I really need to see that null! I was thinking that Data::Printer was eating it, but today I had occasion to run a Data::Printer program inside EShell and I noticed the null was still there!
\ {
blank "",
null "^@",
undefined undef,
zed 0,
zero 0
}
So I just need to get my terminal to show it to me. Or get Data::Printer to output something that my terminal is happier showing me. First, I tried adding a filter to Data::Printer like so
use Data::Printer
filters => {SCALAR => sub { ${$_[0]} =~ s/\0/\\0/gr;}};
but that called my SCALAR filter instead of the built-in SCALAR filter. I couldn't figure out how to call my SCALAR filter and then hand off to the built-in one. So I hacked the the Data::Printer source code to change the nulls in the built-in SCALAR filter.
I ended up surveying a bunch of different data dumpers with a few more whitespace characters added to the mix.
#!/usr/bin/env perl
use v5.14;
use warnings;
my $stuff = {
blank => "",
null => "\0",
undefined => undef,
zed => 0,
zero => '0',
tab => "\t",
newline => "\n",
carriage_return => "\r",
form_feed => "\f",
};
use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
say "\nData::Dumper";
say Data::Dumper::Dumper $stuff;
use Dumpvalue;
say "\nDumpvalue";
say Dumpvalue->new->dumpValue($stuff);
use Data::Dump qw(pp);
say "\nData::Dump";
pp $stuff;
use YAML;
say "\nYAML";
say YAML::Dump $stuff;
use Data::Printer;
say "\nData::Printer";
p $stuff;
use JSON;
say "\nJSON";
say to_json $stuff, {pretty => 1};
use XML::Dumper;
say "\nXML::Dumper";
say pl2xml $stuff;
use Data::Dumper::Concise;
say "\nData::Dumper::Concise";
say Data::Dumper::Concise::Dumper $stuff;
use Data::Dump::Streamer;
say "\nData::Dump::Streamer";
Data::Dump::Streamer::Dump $stuff;
use Data::PrettyPrintObjects;
say "\nData::PrettyPrintObjects";
say PPO $stuff;
use Data::TreeDumper;
say "\nData::TreeDumper";
say DumpTree $stuff;
Running this (with the unmodified Data::Printer) gives
Data::Dumper
$VAR1 = {
'blank' => '',
'carriage_return' => '
',
'form_feed' => '',
'newline' => '
',
'null' => '',
'tab' => ' ',
'undefined' => undef,
'zed' => 0,
'zero' => '0'
};
Dumpvalue
'blank' => ''
'carriage_return' => "\cM"
'form_feed' => "\cL"
'newline' => '
'
'null' => "\c@"
'tab' => "\cI"
'undefined' => undef
'zed' => 0
'zero' => 0
Data::Dump
{
blank => "",
carriage_return => "\r",
form_feed => "\f",
newline => "\n",
null => "\0",
tab => "\t",
undefined => undef,
zed => 0,
zero => 0,
}
YAML
---
blank: ''
carriage_return: "\r"
form_feed: "\f"
newline: "\n"
null: "\0"
tab: ' '
undefined: ~
zed: 0
zero: 0
Data::Printer
\ {
blank "",
carriage_return "",
form_feed "
",
newline "
",
null "",
tab " ",
undefined undef,
zed 0,
zero 0
}
JSON
{
"null" : "\u0000",
"undefined" : null,
"carriage_return" : "\r",
"zed" : "0",
"tab" : "\t",
"blank" : "",
"zero" : "0",
"form_feed" : "\f",
"newline" : "\n"
}
XML::Dumper
<perldata>
<hashref memory_address="0x185ede8">
<item key="blank"></item>
<item key="carriage_return">
</item>
<item key="form_feed"></item>
<item key="newline">
</item>
<item key="null"></item>
<item key="tab"> </item>
<item key="undefined" defined="false"></item>
<item key="zed">0</item>
<item key="zero">0</item>
</hashref>
</perldata>
Data::Dumper::Concise
{
blank => "",
carriage_return => "\r",
form_feed => "\f",
newline => "\n",
null => "\0",
tab => "\t",
undefined => undef,
zed => 0,
zero => 0
}
Data::Dump::Streamer
$HASH1 = {
blank => '',
carriage_return
=> "\r",
form_feed
=> "\f",
newline => "\n",
null => "\0",
tab => "\t",
undefined
=> undef,
zed => 0,
zero => 0
};
Data::PrettyPrintObjects
{
blank => '',
carriage_return => '
',
form_feed => '',
newline => '\n',
null => ,
tab => ' ',
undefined => undef,
zed => 0,
zero => 0
}
Data::TreeDumper
|- blank = [S1]
|- carriage_return = [\r] [S2]
|- form_feed = [S3]
|- newline = [\n] [S4]
|- null = [S5]
|- tab = [\t] [S6]
|- undefined = undef [S7]
|- zed = 0 [S8]
`- zero = 0 [S9]
I'm not sure if I'd rather look at whitespace or escape sequences for things like tabs and newlines, but I'm positive I want to be able to see the difference between an empty string (which is false in Perl) and a string containing a null (which is true in Perl).
Update: (22 Jan 2012) garu applied my patch, so now Data::Printer shows the nulls as \0
$ cpanm Data::Printer
--> Working on Data::Printer
Fetching http://search.cpan.org/CPAN/authors/id/G/GA/GARU/Data-Printer-0.27.tar.gz ... OK
Configuring Data-Printer-0.27 ... OK
Building and testing Data-Printer-0.27 ... OK
Successfully installed Data-Printer-0.27 (upgraded from 0.26)
1 distribution installed
$ perl -MDDP -e '$h = {null => "\0"}; p $h'
\ {
null "\0"
}
Update: (23 Jan 2012) garu spruced it up even more (see comments)!
$ cpanm Data::Printer
--> Working on Data::Printer
Fetching http://search.cpan.org/CPAN/authors/id/G/GA/GARU/Data-Printer-0.28.tar.gz ... OK
Configuring Data-Printer-0.28 ... OK
Building and testing Data-Printer-0.28 ... OK
Successfully installed Data-Printer-0.28 (upgraded from 0.27)
1 distribution installed
$ perl -MDDP -e '$h = {null => "\0"}; p $h'
\ {
null "\0"
}
$ perl -MDDP -e '$h = {foo => "\t"}; p $h'
\ {
tab " "
}
$ perl -MDDP=escape_chars,0 -e '$h = {foo => "\t"}; p $h'
\ {
tab "\t"
}
Recent Comments