用Perl编写报告

时间:2010-05-20 20:26:10

标签: perl format

我正在尝试使用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

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

测试
               下一个项目
               最后一项

读取

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

我已经尝试了很多主要围绕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;

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

任何想法为什么以这种方式声明格式似乎有效? eval有什么特别之处吗?

由于 乔治

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

我认为正在发生的事情是,在我的原始代码中,format语句的行为类似于静态。当首先调用子程序时,它只执行一次。下次调用子程序时,因为格式没有被评估,格式变量$ generatedLine指向上一次调用子程序时的前一个陈旧变量。因此,调用write()只是从最后一个子例程调用中重写相同的文本 使用新方法,每次调用子例程时都会评估格式,因此,格式变量$ generatedLine指向与新子例程调用关联的最新本地$ generatedLine。因此,它打印出正确的数据。