Perl格式化分别显示2个循环

时间:2014-08-19 19:03:25

标签: perl format

我有以下哈希哈希值,

my $hash = {1 => {'a'=>'a1','b'=>'b1', 'c'=>'c1', 'd'=>'d1'},
    2 => {'a'=>'e1','b'=>'f1', 'c'=>'g1', 'd'=>'h1'},
    3 => {'a'=>'i1','b'=>'j1','c'=>'k1', 'd'=>'l1'},
    4 => {'a'=>'m1','b'=>'n1','c'=>'o1','d'=>'p1'}};

我想以perl格式化方式显示上面的哈希哈希值。散列的散列本质上是动态的,所以我们以后也可以使用其他键。

我使用下面的代码生成哈希的哈希到适当的格式。

use strict;
my $hash = {1 => {'a'=>'a1','b'=>'b1', 'c'=>'c1', 'd'=>'d1'},
        2 => {'a'=>'e1','b'=>'f1', 'c'=>'g1', 'd'=>'h1'},
        3 => {'a'=>'i1','b'=>'j1','c'=>'k1', 'd'=>'l1'},
        4 => {'a'=>'m1','b'=>'n1','c'=>'o1','d'=>'p1'}};

my @a = qw(1 2);
my @b = qw(3 4);
&displayreport($hash, \@a);
print "new display\n\n";
&displayreport($hash, \@b);
my($i,$j,$k,$l); 
format STDOUT_TOP =
 A  B   C   D
 -- --  --  --
.
format OUTPUT=
@<< @<< @<< @<<
$i,$j,$k,$l
.

sub displayreport{
    my ($x, $y) = @_;

    $~ = "STDOUT_TOP";
    write;
    foreach(@$y) {
        $i = $hash->{$_}->{a};
        $j = $hash->{$_}->{b};
        $k = $hash->{$_}->{c};
        $l = $hash->{$_}->{d};
        $~ = "OUTPUT";
        write();
    }
}

我得到的输出是,

 A      B       C       D
 --     --      --      --
 A      B       C       D
 --     --      --      --
a1      b1      c1      d1
e1      f1      g1      h1

new display

 A      B       C       D
 --     --      --      --
i1      j1      k1      l1
m1      n1      o1      p1

其中重复第一种情况中的标题。

我需要输出为,

 A      B       C       D
 --     --      --      --
a1      b1      c1      d1
e1      f1      g1      h1

new display

 A      B       C       D
 --     --      --      --
i1      j1      k1      l1
m1      n1      o1      p1

我做错了。请帮助。

2 个答案:

答案 0 :(得分:1)

STDOUT_TOP重命名为STDOUT_TOPX,然后才有效。但我不明白为什么。

答案 1 :(得分:1)

带有_TOP后缀的

format具有Top of Form Processing

的特殊含义

您可以通过打开新文件句柄的输出,并使用$^变量设置$FORMAT_TOP_NAME来更明确地利用此功能。

以下内容证实了这一点:

use strict;
use warnings;

my $hash = {
    1 => { 'a' => 'a1', 'b' => 'b1', 'c' => 'c1', 'd' => 'd1' },
    2 => { 'a' => 'e1', 'b' => 'f1', 'c' => 'g1', 'd' => 'h1' },
    3 => { 'a' => 'i1', 'b' => 'j1', 'c' => 'k1', 'd' => 'l1' },
    4 => { 'a' => 'm1', 'b' => 'n1', 'c' => 'o1', 'd' => 'p1' },
};

displayreport( $hash, [1,2] );

print "\nnew display\n";
displayreport( $hash, [3,4] );

format OUTPUT_TOP =
 A   B   C   D
 --  --  --  --
.

my ( $i, $j, $k, $l );
format OUTPUT=
 @<< @<< @<< @<<
$i,$j,$k,$l
.

sub displayreport {
    my ( $hash, $keys ) = @_;

    open my $fh, '>', \my $output or die "Can't open: $!";
    my $ofh = select($fh);

    $^ = "OUTPUT_TOP";
    $~ = "OUTPUT";

    foreach (@$keys) {
        ($i, $j, $k, $l) = @{$hash->{$_}}{qw(a b c d)};
        write();
    }

    select($ofh);
    close $fh;
    print $output;
}

输出:

 A   B   C   D
 --  --  --  --
 a1  b1  c1  d1
 e1  f1  g1  h1

new display
 A   B   C   D
 --  --  --  --
 i1  j1  k1  l1
 m1  n1  o1  p1

两种替代方案

首先,如果你真的想使用格式,我建议你使用更现代的Perl6::Form

其次,我强烈建议您使用更简单的printfsprintf进行此类基本格式设置并跳过格式:

displayreport( $hash, [1,2] );

print "\nnew display\n";
displayreport( $hash, [3,4] );

sub displayreport {
    my ( $hash, $keys ) = @_;

    my $fmt = " %3s %3s %3s %3s\n";

    printf $fmt, qw(A B C D);
    printf $fmt, qw(-- -- -- --);

    foreach (@$keys) {
        printf $fmt, @{$hash->{$_}}{qw(a b c d)};
    }
}

输出与上一个脚本相同。