格式化哈希内容以生成报告
Formatting a hash content to generate a report
我有一个散列,其中包含如下数据:
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, '-'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)。还提到了作为 header 下划线的破折号 (-),如 '-'x20
.
这是一个好的方法还是我们有任何替代方法来完成这个(任何预定义的 Perl 模块)?
作为使用 Perl 代码格式化的替代方法,请考虑将您的任务拆分为 2 个子任务:
- 使用 Perl 以通用格式写入输出,例如 tab-delimited 文件,然后
- 使用不同的包来格式化tab-delimited文件。
还要考虑一下 header 之后是否需要破折号 (-----
)。如果破折号是可选的,您可以将 perl 的 tsv 输出通过管道传输到 *NIX column
实用程序,如下所示:
perl_script_writing_tsv.pl | column -t -s$'\t'
此处,-t -s$'\t'
选项在制表符上拆分输入而不是默认的空格,并编写对齐良好的输出 table,与您的类似,只是缺少 header 后的破折号.
示例:
代码:
#!/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',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'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
打印 tab-delimited 文件很好地对齐:
示例:
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
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,$node,$delta,$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',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'priority' => 'Medium'
}
);
my $fname = 'hash_events.txt';
open FILE, '>', $fname
or die "Couldn't open $fname: $!";
select(FILE);
$^ = "FILE_TOP";
my($event,$priority,$node,$delta);
for $event (keys %events) {
($node,$delta,$priority) = @{$events{$event}}{qw/node delta priority/};
write;
}
close FILE;
format FILE_TOP =
EVENTID NODE DELTA PRIORITY
-------------------- -------------------- -------------------- --------------------
.
format FILE =
@<<<< @<<<<<<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<
$event,$node,$delta,$priority
.
还有 Perl6::Form
,它允许您在 perl 中使用 Raku-style 格式,其中格式描述是函数的参数,而不是硬编码到您的程序中;基本上,sprintf
服用类固醇。
#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Perl6::Form;
my %hash = (
'150' => {
'priority' => 'High',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'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;
}
我有一个散列,其中包含如下数据:
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, '-'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)。还提到了作为 header 下划线的破折号 (-),如 '-'x20
.
这是一个好的方法还是我们有任何替代方法来完成这个(任何预定义的 Perl 模块)?
作为使用 Perl 代码格式化的替代方法,请考虑将您的任务拆分为 2 个子任务:
- 使用 Perl 以通用格式写入输出,例如 tab-delimited 文件,然后
- 使用不同的包来格式化tab-delimited文件。
还要考虑一下 header 之后是否需要破折号 (-----
)。如果破折号是可选的,您可以将 perl 的 tsv 输出通过管道传输到 *NIX column
实用程序,如下所示:
perl_script_writing_tsv.pl | column -t -s$'\t'
此处,-t -s$'\t'
选项在制表符上拆分输入而不是默认的空格,并编写对齐良好的输出 table,与您的类似,只是缺少 header 后的破折号.
示例:
代码:
#!/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',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'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
打印 tab-delimited 文件很好地对齐:
示例:
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
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,$node,$delta,$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',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'priority' => 'Medium'
}
);
my $fname = 'hash_events.txt';
open FILE, '>', $fname
or die "Couldn't open $fname: $!";
select(FILE);
$^ = "FILE_TOP";
my($event,$priority,$node,$delta);
for $event (keys %events) {
($node,$delta,$priority) = @{$events{$event}}{qw/node delta priority/};
write;
}
close FILE;
format FILE_TOP =
EVENTID NODE DELTA PRIORITY
-------------------- -------------------- -------------------- --------------------
.
format FILE =
@<<<< @<<<<<<<<<<< @<<<<<<<<<<< @<<<<<<<<<<<
$event,$node,$delta,$priority
.
还有 Perl6::Form
,它允许您在 perl 中使用 Raku-style 格式,其中格式描述是函数的参数,而不是硬编码到您的程序中;基本上,sprintf
服用类固醇。
#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
use Perl6::Form;
my %hash = (
'150' => {
'priority' => 'High',
'node' => 'Node1',
'delta' => '00:05:00'
},
'170' => {
'delta' => '00:00:30',
'node' => 'Node2',
'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;
}