用Perl编写报告

geo*_*emp 2 format perl

我试图使用perl写出多个报告文件.每个文件具有相同的结构,但具有不同的数据.所以,我的基本代码看起来像

#begin code
our $log_fh;
open %log_fh, ">" . $logfile

our $rep;

if (multipleReports)
{
   while (@reports) {
     printReport($report[0]);
   }
}

sub printReports
{
   open $rep, ">" . $[0];
   printHeaders();
   printBody();
   close $rep;
}

sub printHeader() {
format HDR =
@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
$generatedLine
.

format HDR_TOP =
.

$rep->format_name("HDR");
$rep->format_top_name("HDR_TOP");

$generatedLine = "test";
write($rep);
$generatedLine = "next item";
write($rep);
$generatedLine = "last header item";
write($rep);
}

sub printBody #There are multiple such sections in my code. For simplicity, I have just shown 1 here
{
 #declare own header and header top. Set report to use these and print items to $rep
}

#end code
Run Code Online (Sandbox Code Playgroud)

以上只是我正在使用的高级代码,我希望我已经抓住了所有重点.但是,出于某种原因,我正确地获得了第一个报告文件输出.第二个文件而不是第一个部分

测试
下一项
最后一项

最后一项
最后一项
最后一项

我已经尝试了很多主要围绕autoflush的选项,但是,对于我的生活无法弄清楚它为什么这样做.我使用的是Perl 5.8.2.任何帮助/指针非常感谢.

谢谢乔治

编辑1我尝试将文件句柄作为参数传递给子例程,但仍然看到了问题.然后我将format语句移到子例程之外,并将$ generated变量声明为全局变量.这似乎解决了这个问题.我认为由于某种原因每次声明格式,子程序被调用,似乎搞乱了它.不确定为什么.虽然很奇怪,我将格式语句移回子程序内部(我不喜欢将所有格式语句中的所有变量声明为全局的想法).但是,这次我改变了声明

my $generatedLine = "";
my $format = "format HDR = \n" .
'@>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' . "\n" .
'$generatedLine' . "\n" .
'.';

my $formatTop = "format HDR_TOP = \n".
'.';

   eval $format;
   eval $formatTop;
Run Code Online (Sandbox Code Playgroud)

这似乎也有效 - 我在多个文件中看到了正确的输出(好吧......我目前只测试2个文件..我明天会做更多的测试).

知道为什么以这种方式声明格式似乎有用吗?eval有什么特别之处吗?

谢谢乔治

FMc*_*FMc 8

我从来没有使用它,但Text :: Report看起来很有希望,如果你正在制作复杂的报告.

关于更一般的问题,你的代码让我觉得你没有运行use strictuse warnings.如果没有,请打开它们.这将提供许多线索.

此外,您似乎正在使用子程序,这很好,但没有利用其主要目的之一 - 即为变量作用域提供明确定义的区域.例如,为什么$rep需要成为全局变量?如果子例程需要一些信息,请将其作为参数传递.特别是当您的程序试图一遍又一遍地执行相同的任务时 - 例如生成一堆报告 - 您需要注意不要允许来自一次迭代的变量在后续迭代期间保留过时的值.

在组织程序时执行一些基本规则将在很大程度上解决这些问题.这是一个简单的例子.

use strict;
use warnings;

# Example usage: perl script.pl foo.txt bar.txt
main(@ARGV);

sub main {
    my @report_names = @_;
    for my $rep_name (@report_names) {
        my @fake_data = map rand(), 1..10;
        printReport($rep_name, @fake_data);
    }
}

sub printReport {
    my ($rep_name, @data) = @_;
    open my $fh, ">", $rep_name or die $!;
    printHeader($fh);
    printBody($fh, @data);
    close $fh;
}

sub printHeader() {
    my $fh = shift;
    print $fh "Header\n";
}

sub printBody {
    my ($fh, @data) = @_;
    print $fh "Body\n";
    print $fh $_, "\n" for @data;
}
Run Code Online (Sandbox Code Playgroud)

  • FWIW我会传递数据作为参考,以避免每次调用都复制它,但在这个阶段引用可能是压倒性的. (2认同)