-2

我有一个可以读取日志的脚本。日志的前三个字符是该客户的代码(即 xxx)。程序启动并运行,然后停止并出现此错误。out.txt 位于所有客户的日志目录中,直到某个客户。这个具有与其他所有相同的权限。该程序停止,并且该客户之后没有任何东西获得该文件。

    $adminDir = "/data1/Scripts";
    $scriptDir =  "/data1/Scripts";
    chomp($toDay = `date +%m-%d-%y`);
    @prodDirs = ();
    open(DIRS, "$scriptDir/production_dirs") or warn "Can't open $scriptDir/production_dirs file: $!\n";
    $count = 0;
    while (<DIRS>) {
             if(index($_, '#') < 0) {
                    chomp($prodDirs[$count++] = $_);
             }
    }
    close(DIRS);

    foreach $jobDir (@prodDirs) {
            @dirFields = split(/\|/, $jobDir);
            $srcDir = $dirFields[0];
            $workDir = "$srcDir";
            $logFile = $workDir . "/log/" . $dirFields[11] . "log";
            $oldLog = $logFile;
            $oldLogBack = $oldLog . "." . $toDay;
            $newLog = $workDir . "/log/" . "out.txt";

            open(FILE, "<$logFile")|| die "Can't open input file $!";
            open(OUT, ">$newLog") || die "Can't open output file $!";
            while(<FILE>) {
                    print OUT if($_=~/(.*)(Jan  1)(.*?)/gs);
            }
     }
4

2 回答 2

4

一些快速的笔记。

为什么使用strictwarnings

使用它可以帮助您更快地发现印刷错误,然后继续找到更重要的问题。

读:

为什么 是三参数而不是二参数形式open()

请记住,two-arg打开的形式已损坏。例如,让我们获取一个名为' foo'. 现在这个文件的开头有一个前导空格。所以不管你去打开它..

open FILE, ' foo'   || die $!;
open FILE, '< foo'  || die $!;
open FILE, '<  foo' || die $!;

看到这里有什么问题吗?这些都不行。另请注意,如果您不小心使用了带有特殊字符的文件名,您的代码可能不会像您预期的那样运行。

这种方法使用起来更加清洁和安全。参考perldoc 打开

open my $fh, '<', 'foo' or die "failed $!";

要记住的事情

  • 使用three-arg打开的形式
  • 用于lexical scalars存储文件句柄引用
  • 通过使用or而不是||检查打开是否成功来避免问题
于 2013-08-16T18:33:41.347 回答
2

我接受了你的程序并添加use strict;use warnings;

use strict;
use warnings;

my $adminDir = "/data1/Scripts";
my $scriptDir =  "/data1/Scripts";

chomp( my $toDay = `date +%m-%d-%y` );
my @prodDir;
open(DIRS, "$scriptDir/production_dirs") or die "Can't open $scriptDir/production_dirs file: $!\n";

my $count = 0;
while ( <DIRS> ) {
    if ( index($_, '#') < 0 ) {
        chomp ( $prodDirs[$count++] = $_ );
    }
}
close(DIRS);

for my $jobDir (@prodDirs) {
    my @dirFields = split(/\|/, $jobDir);
    my $srcDir = $dirFields[0];
    my $workDir = "$srcDir";
    my $logFile = $workDir . "/log/" . $dirFields[11] . "log";
    my $oldLog = $logFile;
    my $oldLogBack = $oldLog . "." . $toDay;
    my $newLog = $workDir . "/log/" . "out.txt";

    open(FILE, "<" , $logFile)|| die "Can't open input file $!";
    open(OUT, ">", $newLog) || die "Can't open output file $!";
    while(<FILE>) {
        print OUT if($_=~/(.*)(Jan  1)(.*?)/gs);
    }
}

我得到的错误:

Global symbol "@prodDirs" requires explicit package name at ./test.pl line 16.
Global symbol "@prodDirs" requires explicit package name at ./test.pl line 21.

在第 10 行中,您初始化@prodDir了 ,但随后在循环中,您使用@prodDirs了 ( 最后带有 an s

这就是为什么每个人都对你说“使用use strict;use warnings;”。这两个 pragma 可以捕获 90% 的编程错误。

于 2013-08-16T20:02:46.643 回答