格式化哈希内容以生成报告

问题描述

我有一个散列,其中包含如下数据:

my %hash = (
    '150' => {
             'priority' => 'High','node' => 'Node1','delta' => '00:05:00'
           },'170' => {
             'delta' => '00:00:30','node' => 'Node2','priority' => 'Medium'
           }
);

我正在使用foreach循环并生成报告(.txt)文件对其进行迭代。

所以,我需要的格式如下:

EVENTID              NODE                 DELTA                PRIORITY
-------------------- -------------------- -------------------- --------------------
150                  Node1                00:05:00             High
170                  Node2                00:00:30             Medium

下面是我的脚本,用于格式化结果:

...
...
open(my $fh,'>',"report_file.txt") or die "Cannot open a file : $!";

printf $fh("%-20s %-20s %-20s %-20s\n",'EVENTID','NODE','DELTA','PRIORITY');
printf $fh("%-20s %-20s %-20s %-20s\n",'-'x20,'-'x20);

foreach my $key (sort keys %hash){
    printf $fh("%-20s %-20s %-20s %-20s\n",$key,$hash{$key}{'node'},$hash{$key}{'delta'},$hash{$key}{'priority'});
}
close $fh;

print "END\n";

它给了我预期的报告,但想确认它是否正确?因为我在这里对空格(-20s)进行硬编码。还提到了将用作标题下划线的破折号(-),例如'-'x20

这是一个很好的方法,还是我们有其他替代方法可以完成此操作(任何预定义的Perl模块)?

解决方法

Perl为数据输出提供format,它最适合您的目标

use strict;
use warnings;

my %events = (
    '150' => {
             'priority' => 'High','node' => 'Node1','delta' => '00:05:00'
           },'170' => {
             'delta' => '00:00:30','node' => 'Node2','priority' => 'Medium'
           }
);

$^ = "STDOUT_TOP";

my($event,$priority,$node,$delta);

for $event (sort keys %events) {
    ($node,$delta,$priority) = @{$events{$event}}{qw/node delta priority/};
    write;
}

format STDOUT_TOP = 
EVENTID              NODE                 DELTA                PRIORITY
-------------------- -------------------- -------------------- --------------------
.

format STDOUT =
@<<<<                @<<<<<<<<<<<         @<<<<<<<<<<<         @<<<<<<<<<<<
$event,$priority
.

输出

EVENTID              NODE                 DELTA                PRIORITY
-------------------- -------------------- -------------------- --------------------
150                  Node1                00:05:00             High
170                  Node2                00:00:30             Medium

附录:以下代码演示了如何使用格式将输出写入文件中

use strict;
use warnings;

my %events = (
    '150' => {
             'priority' => 'High','priority' => 'Medium'
           }
);

my $fname = 'hash_events.txt';

open FILE,'>',$fname
    or die "Couldn't open $fname: $!";
    
select(FILE);

$^ = "FILE_TOP";

my($event,$delta);

for $event (keys %events) {
    ($node,$priority) = @{$events{$event}}{qw/node delta priority/};
    write;
}

close FILE;

format FILE_TOP = 
EVENTID              NODE                 DELTA                PRIORITY
-------------------- -------------------- -------------------- --------------------
.

format FILE =
@<<<<                @<<<<<<<<<<<         @<<<<<<<<<<<         @<<<<<<<<<<<
$event,$priority
.

请参见perlformPerl formats

,

还有Perl6::Form,可让您在perl中使用Raku风格的格式,其中格式说明是函数的参数,而不是硬编码到程序中;基本上是sprintf的类固醇。

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Perl6::Form;

my %hash = (
    '150' => {
             'priority' => 'High','priority' => 'Medium'
           }
);

say 'EVENTID              NODE                 DELTA                PRIORITY';
say '-------------------- -------------------- -------------------- --------------------';
for my $key (sort { $a <=> $b } keys %hash) {
    my $text = form
        '{<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<} {<<<<<<<<<<<<<<<<<<}',$key,@{$hash{$key}}{qw/node delta priority/};
    print $text;
}

,

作为使用Perl代码进行格式化的替代方法,请考虑将您的任务分为2个子任务:

  • 使用Perl以通用格式(例如制表符分隔的文件)写入输出,然后
  • 使用不同程序包格式化制表符分隔的文件。

还请考虑是否需要在标题后加上破折号(-----)。如果破折号是可选的,则可以将perl的tsv输出通过管道传输到* NIX column实用程序中,如下所示:

perl_script_writing_tsv.pl | column -t -s$'\t'

在这里,-t -s$'\t'选项将选项卡上的输入而不是默认的空格分隔开,并写出对齐的输出表,与您的输出表相似,但标题后没有破折号。


示例:

代码:

#!/usr/bin/env perl

use warnings;
use strict;
use feature qw( say );

# Renamed the hash for clarity: please rename according to your
# knowledge domain.
my %benchmarks_for_eventid = (
    '150' => {
             'priority' => 'High','priority' => 'Medium'
           }
);

my $delim = "\t";
my @benchmarks_for_eventid_fields = qw( node delta priority );
    
say join $delim,map { uc } 'eventid',@benchmarks_for_eventid_fields;

# Using numeric 'sort',since eventids are likely integers,not
# strings:
foreach my $eventid ( sort { $a <=> $b } keys %benchmarks_for_eventid ) {
    say join $delim,$eventid,map { $benchmarks_for_eventid{ $eventid }{ $_ } }
        @benchmarks_for_eventid_fields;
}

script | column ...的输出:

EVENTID  NODE   DELTA     PRIORITY
150      Node1  00:05:00  High
170      Node2  00:00:30  Medium

使用column打印以制表符分隔的文件,并使其对齐:

示例:

perl -le '
print join "\t",qw(col1 col2 col3);
print join "\t",q{r1 c1},q{r1 c2 loooooooong string},q{r1 c3};
print join "\t",q{r2 c1},q{r2 c2},q{r2 c3};
' | column -t -s$'\t'

打印:

col1   col2                      col3
r1 c1  r1 c2 loooooooong string  r1 c3
r2 c1  r2 c2                     r2 c3

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...