Data::Dumper - 将 Perl 数据结构转换为字符串,适合打印和 eval
use Data::Dumper;
# simple procedural interface
print Dumper($foo, $bar);
# extended usage with names
print Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
# configuration variables
{
local $Data::Dumper::Purity = 1;
eval Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
}
# OO usage
my $d = Data::Dumper->new([$foo, $bar], [qw(foo *ary)]);
...
print $d->Dump;
...
$d->Purity(1)->Terse(1)->Deepcopy(1);
eval $d->Dump;
给定一个标量或引用变量列表,以 Perl 语法输出其内容。引用也可以是对象。每个变量的内容在单个 Perl 语句中输出。正确处理自引用结构。
返回值可以 eval
以获得与原始引用结构相同的副本。(请考虑从不受信任的来源 eval
代码的安全隐患!)
任何与传递进来的引用相同的引用将被命名为$VAR
n(其中n 是一个数字后缀),而其他对$VAR
n 中子结构的重复引用将使用箭头符号进行适当的标记。如果使用Dump()
方法,您可以指定要转储的单个值的名称,或者您可以将默认的$VAR
前缀更改为其他内容。请参阅下面的 "配置变量或方法" 中的 $Data::Dumper::Varname
和 $Data::Dumper::Terse
。
自引用结构的默认输出可以被eval
,但对$VAR
n 的嵌套引用将是未定义的,因为使用一个 Perl 语句无法构建递归结构。您应该将Purity
标志设置为 1 以获取额外的语句,这些语句将正确填充这些引用。此外,如果在严格模式下被eval
,您需要确保它访问的任何变量都已事先声明。
在扩展使用形式中,要转储的引用可以被赋予用户指定的名称。如果名称以*
开头,则输出将描述为哈希和数组以及代码引用提供的引用的解引用类型。如果设置了Terse
标志,则将尽可能避免输出名称。
在许多情况下,用于设置对象内部状态的方法将返回对象本身,因此方法调用可以方便地链接在一起。
有多种输出样式,所有这些样式都通过设置Indent
标志来控制。有关详细信息,请参阅下面的 "配置变量或方法"。
返回一个新创建的Data::Dumper
对象。第一个参数是一个匿名数组,其中包含要转储的值。可选的第二个参数是一个匿名数组,其中包含值的名称。名称不需要有前导的$
符号,并且必须由字母数字字符组成。您可以用*
开头一个名称来指定必须转储解引用类型而不是引用本身,对于 ARRAY 和 HASH 引用。
如果值的名称未定义,则将使用$Data::Dumper::Varname
指定的前缀以及一个数字后缀。
Data::Dumper 将对在转储值时遇到的所有引用进行编目。交叉引用(以 Perl 语法中的子结构名称的形式)将插入所有可能的点,保留原始值集中任何结构上的相互依赖关系。结构遍历是深度优先的,并且从第一个提供的值到最后一个值按顺序进行。
返回存储在对象中的值的字符串化形式(保留它们提供给new
的顺序),受以下配置选项的约束。在列表上下文中,它返回一个字符串列表,对应于提供的值。
第二种形式为了方便起见,在立即转储对象之前,简单地对它的参数调用new
方法。
查询或添加到已遇到引用的内部表中。您必须使用Reset
来显式清除表(如果需要)。此类引用不会被转储;相反,它们的名称将在它们随后遇到的任何地方插入。这对于正确转储子例程引用特别有用。
期望一个匿名哈希,包含名称 => 值对。名称的规则与new
中的相同。如果未提供参数,将在列表上下文中返回“已看到”的名称 => 值对列表。否则,返回对象本身。
查询或替换将被转储的值的内部数组。在不带参数的情况下调用时,返回一个列表形式的值。在使用对替换值数组的引用调用时,返回对象本身。在使用任何其他类型的参数调用时,将导致程序终止。
查询或替换将被转储的值的用户提供的名称的内部数组。在不带参数的情况下调用时,返回名称。在使用替换名称数组调用时,返回对象本身。如果替换名称的数量超过要命名的值的数量,则多余的名称将不会被使用。如果替换名称的数量少于要命名的值的数量,则替换名称列表将被耗尽,剩余的值将不会被重命名。在使用任何其他类型的参数调用时,将导致程序终止。
清除“已看到”引用的内部表,并返回对象本身。
返回列表中值的字符串化形式,受以下配置选项的影响。这些值将在输出中被命名为$VAR
n,其中n是数字后缀。在列表上下文中将返回一个字符串列表。
使用过程式接口时,可以使用多个配置变量来控制生成的输出类型。这些变量通常在代码块中局部化
,以便代码的其他部分不受更改的影响。
这些变量决定了通过调用new
方法创建的对象的默认状态,但不能用于更改对象的后续状态。应使用等效的方法名称来查询或设置对象的内部状态。
当使用参数调用方法形式时,它们会返回对象本身,以便可以很好地将它们链接在一起。
$Data::Dumper::Indent 或 $OBJ->Indent([NEWVAL])
控制缩进样式。它可以设置为 0、1、2 或 3。样式 0 输出没有换行符、缩进或列表项之间空格的输出。它是仍然可以称为有效 perl 的最紧凑的格式。样式 1 输出可读形式,带有换行符,但没有花哨的缩进(结构中的每个级别都简单地缩进固定数量的空格)。样式 2(默认)输出一种非常可读的形式,它将哈希键对齐。样式 3 类似于样式 2,但还用其索引注释数组的元素(但注释在它自己的行上,因此数组输出消耗两倍的行数)。样式 2 是默认值。
$Data::Dumper::Trailingcomma 或 $OBJ->Trailingcomma([NEWVAL])
控制是否在数组或哈希的最后一个元素后添加逗号。即使为真,当数组或哈希的最后一个元素和结束括号出现在同一行时,它们之间也不会添加逗号。默认值为 false。
$Data::Dumper::Purity 或 $OBJ->Purity([NEWVAL])
控制输出可以eval
以重新创建提供的引用结构的程度。将其设置为 1 将输出其他 perl 语句,这些语句将正确地重新创建嵌套引用。默认值为 0。
$Data::Dumper::Pad 或 $OBJ->Pad([NEWVAL])
指定将作为前缀添加到输出每一行的字符串。默认情况下为空字符串。
$Data::Dumper::Varname 或 $OBJ->Varname([NEWVAL])
包含用于在输出中标记变量名称的前缀。默认值为“VAR”。
$Data::Dumper::Useqq 或 $OBJ->Useqq([NEWVAL])
设置后,启用使用双引号来表示字符串值。空格(空格除外)将表示为[\n\t\r]
,“不安全”字符将被反斜杠转义,不可打印字符将输出为带引号的八进制整数。默认值为 0。
$Data::Dumper::Terse 或 $OBJ->Terse([NEWVAL])
当设置时,Data::Dumper 将以原子/术语的形式输出单个非自引用值,而不是语句。这意味着将尽可能避免使用 $VAR
n 名称,但请注意,此类输出可能并不总是可由 eval
解析。
$Data::Dumper::Freezer 或 $OBJ->Freezer([NEWVAL])
可以设置为方法名称,或设置为空字符串以禁用该功能。Data::Dumper 将通过对象调用该方法,然后再尝试将其字符串化。此方法可以更改对象的内容(例如,如果它包含从 C 分配的数据),甚至可以在不同的包中重新祝福它。客户端负责确保可以通过对象调用指定的方法,并且在调用该方法后,对象最终只包含 Perl 数据类型。默认为空字符串。
如果对象不支持指定的方法(使用 UNIVERSAL::can() 确定),则将跳过调用。如果方法死亡,将生成警告。
$Data::Dumper::Toaster 或 $OBJ->Toaster([NEWVAL])
可以设置为方法名称,或设置为空字符串以禁用该功能。Data::Dumper 将为使用语法 bless(DATA, CLASS)->METHOD()
倾倒的任何对象发出方法调用。请注意,这意味着指定的方法必须对对象执行任何必要的修改(例如,在其中创建新的状态,和/或在不同的包中重新祝福它),然后返回它。客户端负责确保可以通过对象调用该方法,并且它返回一个有效的对象。默认为空字符串。
$Data::Dumper::Deepcopy 或 $OBJ->Deepcopy([NEWVAL])
可以设置为布尔值以启用结构的深层复制。然后,只有在绝对必要时(即,为了打破引用循环)才会进行交叉引用。默认为 0。
$Data::Dumper::Quotekeys 或 $OBJ->Quotekeys([NEWVAL])
可以设置为布尔值以控制是否引用哈希键。定义的假值将在看起来像简单字符串时避免引用哈希键。默认为 1,它将始终将哈希键括在引号中。
$Data::Dumper::Bless 或 $OBJ->Bless([NEWVAL])
可以设置为一个字符串,该字符串指定用于创建对象的 bless
内置运算符的替代方法。应该存在具有指定名称的函数,并且应该接受与内置函数相同的参数。默认为 bless
。
$Data::Dumper::Pair 或 $OBJ->Pair([NEWVAL])
可以设置为一个字符串,指定哈希键和值之间的分隔符。要将嵌套的哈希、数组和标量值转储到 JavaScript,请使用:$Data::Dumper::Pair = ' : ';
。在 JavaScript 中实现 bless
留给读者练习。存在一个具有指定名称的函数,它接受与内置函数相同的参数。
默认值为: =>
。
$Data::Dumper::Maxdepth 或 $OBJ->Maxdepth([NEWVAL])
可以设置为一个正整数,指定超出该深度的结构将不再深入。当 Data::Dumper::Purity
设置时,此选项无效。(在调试器中很有用,因为我们通常不想看到太多内容)。默认值为 0,表示没有最大深度。
$Data::Dumper::Maxrecurse 或 $OBJ->Maxrecurse([NEWVAL])
可以设置为一个正整数,指定超出该深度的结构递归将抛出异常。这是为了防止在转储过深的结构时,perl 耗尽堆栈空间的安全措施。可以设置为 0 来移除限制。默认值为 1000。
$Data::Dumper::Useperl 或 $OBJ->Useperl([NEWVAL])
可以设置为一个布尔值,控制是否使用 Data::Dumper
的纯 Perl 实现。Data::Dumper
模块是双重实现,几乎所有功能都用纯 Perl 和 XS('C')编写。由于 XS 版本速度更快,因此如果可能,它将始终使用。此选项允许您覆盖默认行为,通常仅用于测试目的。默认值为 0,表示如果可能,将使用 XS 实现。
$Data::Dumper::Sortkeys 或 $OBJ->Sortkeys([NEWVAL])
可以设置为一个布尔值,控制是否按排序顺序转储哈希键。真值将导致所有哈希的键按 Perl 的默认排序顺序转储。也可以设置为一个子程序引用,该子程序引用将针对转储的每个哈希调用。在这种情况下,Data::Dumper
将针对每个哈希调用一次子程序,并将哈希的引用传递给它。子程序的目的是返回一个对将要转储的键的引用的引用,以及它们应该转储的顺序。使用此功能,您可以控制键的顺序以及实际使用的键。换句话说,此子程序充当过滤器,您可以通过它排除某些键不被转储。默认值为 0,表示哈希键不会排序。
$Data::Dumper::Deparse 或 $OBJ->Deparse([NEWVAL])
可以设置为一个布尔值,控制是否将代码引用转换为 perl 源代码。如果设置为真值,B::Deparse
将用于获取代码引用的源代码。在旧版本中,使用此选项在转储数据结构的代码引用以外的部分时会造成明显的性能损失,但现在不再是这种情况。
注意:仅当您知道您的代码引用将被 B::Deparse
正确重建时,才使用此选项。
$Data::Dumper::Sparseseen 或 $OBJ->Sparseseen([NEWVAL])
默认情况下,Data::Dumper 会构建一个“已见”标量哈希,用于记录序列化过程中遇到的标量。这非常昂贵。这个“已见”哈希对于支持和检测循环引用至关重要。它可以通过 Seen()
调用暴露给用户,用于写入和读取。
如果您作为用户不需要显式访问“已见”哈希,那么您可以设置 Sparseseen
选项,允许 Data::Dumper 避免为已知只有一个引用的标量构建“已见”哈希。如果您使用 XS 实现,这将大大加快序列化速度。
注意:如果您开启了 Sparseseen
,那么您不能依赖“已见”哈希的内容,因为它的内容将是实现细节!
运行这些代码片段,快速了解该模块的行为。当您完成这些示例后,您可能希望添加或更改上面描述的各种配置变量,以查看它们的行为。(有关更多示例,请参阅 Data::Dumper 发行版中的测试套件。)
use Data::Dumper;
package Foo;
sub new {bless {'a' => 1, 'b' => sub { return "foo" }}, $_[0]};
package Fuz; # a weird REF-REF-SCALAR object
sub new {bless \($_ = \ 'fu\'z'), $_[0]};
package main;
$foo = Foo->new;
$fuz = Fuz->new;
$boo = [ 1, [], "abcd", \*foo,
{1 => 'a', 023 => 'b', 0x45 => 'c'},
\\"p\q\'r", $foo, $fuz];
########
# simple usage
########
$bar = eval(Dumper($boo));
print($@) if $@;
print Dumper($boo), Dumper($bar); # pretty print (no array indices)
$Data::Dumper::Terse = 1; # don't output names where feasible
$Data::Dumper::Indent = 0; # turn off all pretty print
print Dumper($boo), "\n";
$Data::Dumper::Indent = 1; # mild pretty print
print Dumper($boo);
$Data::Dumper::Indent = 3; # pretty print with array indices
print Dumper($boo);
$Data::Dumper::Useqq = 1; # print strings in double quotes
print Dumper($boo);
$Data::Dumper::Pair = " : "; # specify hash key/value separator
print Dumper($boo);
########
# recursive structures
########
@c = ('c');
$c = \@c;
$b = {};
$a = [1, $b, $c];
$b->{a} = $a;
$b->{b} = $a->[1];
$b->{c} = $a->[2];
print Data::Dumper->Dump([$a,$b,$c], [qw(a b c)]);
$Data::Dumper::Purity = 1; # fill in the holes for eval
print Data::Dumper->Dump([$a, $b], [qw(*a b)]); # print as @a
print Data::Dumper->Dump([$b, $a], [qw(*b a)]); # print as %b
$Data::Dumper::Deepcopy = 1; # avoid cross-refs
print Data::Dumper->Dump([$b, $a], [qw(*b a)]);
$Data::Dumper::Purity = 0; # avoid cross-refs
print Data::Dumper->Dump([$b, $a], [qw(*b a)]);
########
# deep structures
########
$a = "pearl";
$b = [ $a ];
$c = { 'b' => $b };
$d = [ $c ];
$e = { 'd' => $d };
$f = { 'e' => $e };
print Data::Dumper->Dump([$f], [qw(f)]);
$Data::Dumper::Maxdepth = 3; # no deeper than 3 refs down
print Data::Dumper->Dump([$f], [qw(f)]);
########
# object-oriented usage
########
$d = Data::Dumper->new([$a,$b], [qw(a b)]);
$d->Seen({'*c' => $c}); # stash a ref without printing it
$d->Indent(3);
print $d->Dump;
$d->Reset->Purity(0); # empty the seen cache
print join "----\n", $d->Dump;
########
# persistence
########
package Foo;
sub new { bless { state => 'awake' }, shift }
sub Freeze {
my $s = shift;
print STDERR "preparing to sleep\n";
$s->{state} = 'asleep';
return bless $s, 'Foo::ZZZ';
}
package Foo::ZZZ;
sub Thaw {
my $s = shift;
print STDERR "waking up\n";
$s->{state} = 'awake';
return bless $s, 'Foo';
}
package main;
use Data::Dumper;
$a = Foo->new;
$b = Data::Dumper->new([$a], ['c']);
$b->Freezer('Freeze');
$b->Toaster('Thaw');
$c = $b->Dump;
print $c;
$d = eval $c;
print Data::Dumper->Dump([$d], ['d']);
########
# symbol substitution (useful for recreating CODE refs)
########
sub foo { print "foo speaking\n" }
*other = \&foo;
$bar = [ \&other ];
$d = Data::Dumper->new([\&other,$bar],['*other','bar']);
$d->Seen({ '*foo' => \&foo });
print $d->Dump;
########
# sorting and filtering hash keys
########
$Data::Dumper::Sortkeys = \&my_filter;
my $foo = { map { (ord, "$_$_$_") } 'I'..'Q' };
my $bar = { %$foo };
my $baz = { reverse %$foo };
print Dumper [ $foo, $bar, $baz ];
sub my_filter {
my ($hash) = @_;
# return an array ref containing the hash keys to dump
# in the order that you want them to be dumped
return [
# Sort the keys of %$foo in reverse numeric order
$hash eq $foo ? (sort {$b <=> $a} keys %$hash) :
# Only dump the odd number keys of %$bar
$hash eq $bar ? (grep {$_ % 2} keys %$hash) :
# Sort keys in default order for all other hashes
(sort keys %$hash)
];
}
由于 Perl 子例程调用语义的限制,您不能传递数组或哈希。在前面加上 \
来传递它的引用。这将在 Perl 拥有子例程原型后得到解决。目前,您需要使用扩展用法形式,并在名称前面加上 *
以将其输出为哈希或数组。
Data::Dumper
对 CODE 引用进行了欺骗。如果在处理的结构中遇到代码引用(并且您没有设置 Deparse
标志),则会插入一个包含字符串 '"DUMMY"' 的匿名子例程,如果设置了 Purity
,则会打印警告。您可以 eval
结果,但请记住,创建的匿名子例程只是一个占位符。即使使用 Deparse
标志,在某些情况下也会产生在传递给 eval
后行为不同的结果;请参阅 B::Deparse 的文档。
SCALAR 对象具有最奇怪的 bless
解决方法。
不同运行的 Perl 会有不同的哈希键排序。此更改是为了提高安全性,请参阅 "perlsec 中的算法复杂度攻击"。这意味着如果数据包含哈希,则不同运行的 Perl 将具有不同的 Data::Dumper 输出。如果您需要从不同运行的 Perl 获得相同的 Data::Dumper 输出,请使用环境变量 PERL_HASH_SEED,请参阅 "perlrun 中的 PERL_HASH_SEED"。使用此方法将恢复旧的(平台特定的)排序:一个更漂亮的解决方案可能是使用 Data::Dumper 的 Sortkeys
过滤器。
Gurusamy Sarathy [email protected]
版权所有 (c) 1996-2019 Gurusamy Sarathy。保留所有权利。本程序是自由软件;您可以在与 Perl 本身相同的条款下重新分发和/或修改它。
版本 2.188
perl(1)