【问题标题】:Writing reports with Perl用 Perl 写报告
【发布时间】:2011-02-22 01:56:56
【问题描述】:

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

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

测试
下一项
最后一项

读取

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

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

谢谢 乔治

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

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

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

   eval $format;
   eval $formatTop;

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

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

谢谢 乔治

【问题讨论】:

  • @user346526:欢迎来到 StackOverflow!我已经为您格式化了代码块——为了在以后的问题和答案中达到相同的结果,发布代码后,选择它并单击工具栏中的“代码”按钮。
  • @josh:谢谢..有那么一刻我想知道它是如何神奇地格式化的:)
  • @georgemp : 你在使用strictwarnings 吗?他们往往会帮助摆脱愚蠢的小事情。此外,请花时间确保您的代码与问题要求的一样完整并且没有错误。我已经发现了一些错别字,我敢肯定你不是故意的;处理好这些小事后,它可以帮助其他人深入了解您的问题的本质。
  • 一些可能的拼写错误:while (@reports) { printReport($report[0]); } 将一遍又一遍地打印第一份报告。 $_[0] 是例程的第一个参数,而不是 $[0]
  • Perl 格式有点奇怪和笨重。除非您要做复杂的报告,否则请考虑使用printf

标签: perl format


【解决方案1】:

我从未使用过它,但如果您要制作复杂的报告,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;
}

【讨论】:

  • FWIW 我会将数据作为参考传递,以避免每次调用都复制它,但在这个阶段参考可能会不堪重负。
  • @FM - 我会试试这个......将文件句柄作为参数传递。我确实有使用严格;并使用警告;在我的程序中。它不会抛出任何错误/警告。 @FM/Schwern - 感谢您的回复
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    相关资源
    最近更新 更多