当您尝试使用Perl打印数组或哈希表时,出现Array(0xd3888)是什么意思?

13

当你尝试打印数组或哈希表时,看到以下内容,Array(0xd3888) 或 HASH(0xd3978),这意味着什么?

示例

代码

my @data = (  
['1_TEST','1_T','1_TESTER'],  
['2_TEST','2_T','2_TESTER'],  
['3_TEST','3_T','3_TESTER'],  
['4_TEST','4_T','4_TESTER'],  
['5_TEST','5_T','5_TESTER'],  
['6_TEST','6_T','^_TESTER']  
);  

foreach my $line (@data) {  
   chomp($line);  
   @random = split(/\|/,$line);  
   print "".$random[0]."".$random[1]."".$random[2]."","\n";  
}  

结果

ARRAY(0xc1864)  
ARRAY(0xd384c)  
ARRAY(0xd3894)  
ARRAY(0xd38d0)  
ARRAY(0xd390c)  
ARRAY(0xd3948)  

2
可能是重复的问题,与https://dev59.com/L0zSa4cB1Zd3GeqPlUth相同。 - Eric Strom
SO 2360192与此有松散的关联,但此处的触发器是显式的“[...]”符号,而在另一个中则不太直接。 - Jonathan Leffler
3个回答

20
很难确定你是否有意为之,但你得到数组引用的原因是你没有打印你认为的内容。 当你迭代@data的'行'时,开始做得很对。
foreach my $line (@data) { ... }
然而,下一行就有问题了。看起来你混淆了文本字符串和数组结构。每一行都包含字符串,但是Perl将 @data 视为数组,而不是字符串。
使用split函数将字符串转换成数组。它不能操作数组!chomp也是如此(有一个无关紧要的例外)。
你需要做的是用以下代码替换 foreach 循环的内容:
foreach my $line (@data) {

    print $line->[0].", ".$line->[1].", ".$line->[2]."\n";
}
你会注意到->符号,这是有原因的。 $line指的是一个数组,而不是数组本身。箭头->用于解引用该数组,从而允许您访问由$line引用的数组中的单个元素。
如果您对使用箭头进行解引用不太熟悉(大多数初学者通常都不熟悉),您可以像下面示例中所示创建一个临时数组,然后使用该数组。
foreach my $line (@data) {

    my @random = @{ $line };
    print $random[0].", ".$random[1].", ".$random[2]."\n";
}

输出

1_TEST, 1_T, 1_TESTER
2_TEST, 2_T, 2_TESTER
3_TEST, 3_T, 3_TESTER
4_TEST, 4_T, 4_TESTER
5_TEST, 5_T, 5_TESTER
6_TEST, 6_T, ^_TESTER

一个单行操作可能会像这样 print "@$_\n" for @data;(有点过头了),但是如果你只是想打印数组以查看它的样子(比如说,用于调试目的),我建议使用Data::Dump模块,它可以为您漂亮地打印出数组和哈希,而不需要你过多地担心。

只需在脚本开头放置use Data::Dump 'dump';,然后dump @data;。就这么简单!


4

这意味着你没有一个数组,而是有一个指向数组的引用。

需要注意的是,数组是使用圆括号指定的 - 就像一个列表一样;当你使用方括号表示法时,你正在创建一个对数组的引用。

foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

说明区别:

my @data = (
['1_TEST','1_T','1_TESTER'],
['2_TEST','2_T','2_TESTER'],
['3_TEST','3_T','3_TESTER'],
['4_TEST','4_T','4_TESTER'],
['5_TEST','5_T','5_TESTER'],
['6_TEST','6_T','^_TESTER']
);

# Original print loop
foreach my $line (@data)
{
    chomp($line);
    @random = split(/\|/,$line);
    print "".$random[0]."".$random[1]."".$random[2]."","\n";
}

# Revised print loop
foreach my $line (@data)
{
    my @array = @$line;
    print "$array[0] - $array[1] - $array[2]\n";
}

输出

ARRAY(0x62c0f8)
ARRAY(0x649db8)
ARRAY(0x649980)
ARRAY(0x649e48)
ARRAY(0x649ec0)
ARRAY(0x649f38)
1_TEST - 1_T - 1_TESTER
2_TEST - 2_T - 2_TESTER
3_TEST - 3_T - 3_TESTER
4_TEST - 4_T - 4_TESTER
5_TEST - 5_T - 5_TESTER
6_TEST - 6_T - ^_TESTER

3
你提到的数组嵌套数组的例子毫无意义。它们只会被压成一堆 - 这就是为什么你必须使用引用的原因。 - rjh
我已经编辑了这个示例,所以它不会尝试使用()符号。现在的注释没有太多意义,因为它们指的是未显示的内容。 - Jonathan Leffler

-2

你正在打印哈希表或数组的引用,而不是其中的内容。

在你描述的特定代码中,我记得Perl会自动将foreach循环索引变量(在你的代码中是my $line)转换为一个“别名”(一种引用,我想),代表每个循环阶段的值。

所以$line是对@data[x]的引用...每次迭代时都是某个数组。要访问@data[0]中的元素之一,需要使用$符号(因为@data[0]中的元素是标量)。但是,$line[0]是对不存在的某个包/全局变量的引用(顺便说一下,use warnings; use strict;会告诉你这一点)。

[在Ether指出我的无知后进行编辑] @data是一个匿名数组引用列表;每个引用都包含一系列标量。因此,你必须使用我下面描述的显式解引用方式:

你需要的是更像这样的东西:

print ${$line}[0], ${$line}[1], ${$line}[2], "\n";

请注意,${xxx}[0] 确保对 xxx 进行了解引用,然后对解引用的结果执行索引,最终将其提取为标量。
我也进行了测试:
print $$line[0], $$line[1], $$line[2], "\n";

...看起来它能够工作。(然而,我认为第一种形式更清晰,即使它更冗长)。

就我个人而言,我把这归咎于 Perl 中的另一个陷阱。

[进一步发表意见] 我仍然把这算作是一个“陷阱”。像这样的东西,以及对这个问题的大多数回答在技术上都是正确的,但完全没有展示出任何努力来帮助原始的发布者,这再次提醒我为什么那么多年前我转向了 Python。当然,我发布的代码可以工作,并且可能实现了 OP 所尝试的目标。我的解释完全是错误的。我在 `perlsyn` 手册中看到了“alias”这个词,并记得在某个地方有一些奇怪的语义;所以我完全忽略了[...]正在创建一个匿名引用的部分。除非你深深地喝了 Perl Kool-Aid,否则甚至最简单的代码也无法解释。

2
如果你认为这是一个“陷阱”,请重新阅读perldoc perlreftutperldoc perldscperldoc perllol。foreach迭代器是对原始数据的引用这一事实与此问题无关。 - Ether
@Ether:换句话说,它比我想象的更加晦涩。我将我的帖子更新为对所发生情况的不同解释。 - Jim Dennis
我真的应该阅读六份不同的文档,才能理解五行相对简单的代码中发生了什么?这里的Perl爱好者们都没有愿意超越帖子表面的部分,试图解释为什么他得到了引用以及如何取消引用。(这让我想起了一个古老的格言,当你想得到正确答案时,在USENet上发布错误信息)。 - Jim Dennis
1
你是在拿我开玩笑吗?有两个答案解释了为什么他会得到引用以及如何去除它们,这两个答案都比你的帖子早。 此外,你不需要阅读 Ether 链接的三个(六个从哪里来的)文档。perlreftut 是一个引用教程,应该足以回答具体问题。第二个文档是 Data Structures Cookbook,展示了如何创建和访问许多不同的复合结构的示例,它本身就可以回答你的问题。第三个文档是一个工作在列表中的列表的教程,也提供了你所需的信息。 - daotoad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接