1

嘿,perl 修道士们,

我仍在思考如何正确取消引用。(我在发布之前阅读了类似的帖子,但不幸的是,我对这个概念仍然有些模糊。)

我有以下数组,它在内部由两个数组组成。(顺便说一句,我正在使用严格和警告的编译指示。)

use strict; use warnings;
my @a1; my @a2;

在哪里:

@a1 = ( "1MB", "2MB", ... )

和..

@a2 = ( "/home", "/home/debug", ... )

@a1 和 @a2 都是包含 51 行的数组。所以,我将这些填充到我的第二个数组中。

my @b;
push (@b, [ @a1, @a2 ]);

但是,当我尝试打印@b 的结果时:

sub newl { print "\n"; print "\n"; }
my $an1; my @an1;
$an1 = $#a1;
@an1 = ( 0, 1..$an1 );

for my $i (@an1) { print @b[$i]; &newl; }

我看到对数组的引用:

ARRAY(0x81c0a10)
  .
ARRAY(0x81c0a50)
  .
  .
  .

如何正确打印此数组?我知道我需要取消对数组的引用,我不知道该怎么做。我尝试这样填充我的数组:

push (@b, [ \@a1, \@a2 ]);

产生相同的结果。我也试过:

for my $i (@an1) { print @{$b[$i]}; &newl; }

不幸的是,由于将 0 作为数组引用而导致错误?

Can't use string ("0") as an ARRAY ref while "strict refs" in use at p_disk_ex6.pl line 42.

任何建议都非常感谢!

4

3 回答 3

1

一个简短的示例程序,可能会对您有所帮助:

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);
# equivalent long version:
# my @b = ();
# $b[0] = \@a1;
# $b[1] = \@a2;

for (my $i = 0; $i <= $#a2; $i++) {
    print "a1[$i]: $b[0][$i]\n";
    print "a2[$i]: $b[1][$i]\n";
    print "\n";
}

在您的示例中,您将一个匿名的 arrayref [] 推入@b。因此 $b[0] 包含 arrayref。

my @b;
push (@b, [ \@a1, \@a2 ]);
# this corresponds to:
# $b[0][0] = \@a1;
# $b[0][1] = \@a2;

在您编写 [@a1, @a2] 的示例中,您正在创建一个 array_ref,其中包含连接的数组 @a1 和 @a2(首先是 @a1 的所有元素,然后是 @a2 的所有元素):

my @b;
push(@b , [@a1, @a2]);
# $b[0] = ['1MB' , '2MB', '10Mb', '7MB', '/foo', '/bar', '/flub', '/blub']
于 2012-08-08T14:00:57.280 回答
0

即使很简单,这也有效

use strict;
use warnings;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (@a1, @a2);
print "@b";
于 2013-02-26T20:53:13.530 回答
0

如果您想要一个不假设每个子数组中有多少元素的通用解决方案,并且还允许任意级别的嵌套,那么您最好使用其他人已经编写的用于显示递归数据的包结构。一个特别流行的是 YAML,如果你还没有它,你可以通过运行 cpan 来安装它:

$ cpan
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.9800)
Enter 'h' for help.

cpan[1]> install YAML

然后您可以轻松地显示任意数据结构。用一个简单的例子来演示:

use YAML;

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2);

print Dump(\@b);

结果输出

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub

对于一个稍微复杂的例子

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

---
-
  - 1MB
  - 2MB
  - 10MB
  - 7MB
-
  - /foo
  - /bar
  - /flub
  - /blub
- a: 0
  b: 1

要阅读此内容,第 1 列中的三个“-”字符表示包含三个元素的数组。前两个元素各有四个子元素(第 3 列中带有“-”的行)。第三个外部元素是哈希引用,因为它由“键:值”对组成。

YAML 的一个很好的特性是您可以使用它将任何递归数据结构转储到文件中,除了那些具有子例程引用的文件,然后稍后使用 Load 将其读回。

如果你真的必须滚动你自己的显示例程,那当然是可能的,但是如果你递归地编写它,你会更容易。您可以使用 ref 检查您的参数是数组引用还是哈希引用(或标量引用):

my @a1 = qw(1MB 2MB 10MB 7MB);
my @a2 = qw(/foo /bar /flub /blub);

my @b = (\@a1, \@a2,
         { a => 0, b => 1 } );

print_recursive(\@b);
print "\n";

sub print_recursive {
    my ($obj) = @_;

    if (ref($obj) eq 'ARRAY') {
        print "[ ";
        for (my $i=0; $i < @$obj; $i++) {
            print_recursive($obj->[$i]);
            print ", " if $i < $#$obj;
        }
        print " ]";
    }
    elsif (ref($obj) eq 'HASH') {
        print "{ ";
        my @keys = sort keys %$obj;
        for (my $i=0; $i < @keys; $i++) {
            print "$keys[$i] => ";
            print_recursive($obj->{$keys[$i]});
            print ", " if $i < $#keys;
        }
        print " }";
    }
    else {
        print $obj;
    }
}       

产生输出

[ [ 1MB, 2MB, 10MB, 7MB ], [ /foo, /bar, /flub, /blub ], { a => 0, b => 1 } ]

我没有编写示例代码来担心漂亮的打印,也没有处理标量、子例程或祝福对象引用,但它应该让您了解如何编写一个相当通用的递归数据结构转储程序。

于 2014-04-12T03:34:19.447 回答