我正在尝试使用Perl创建一个程序,该程序将读取长度超过40,000行的文件的数据并解析每条消息以从中提取错误消息。
我使用的数据样本如下所示:
--------All Messages---------
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
ERROR: there was an error transferring data .
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
ERROR: there was an error transferring the data and the error message spans
more than 1 line of code and may also contain newline characters as well .
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
SUCCESS: data transferred successfully .
---------END REPOSITORY---------
日志中的每条消息都有以下共同点:
1)它以SUCCESS或ERROR开头,具体取决于结果
2)所有消息都将以<whitespace><period><newline>
以下是我编写的代码但由于某种原因我似乎无法调试它。非常感谢任何帮助。
open(FH,$filetoparse);
{
# following line is supposed to change the delimiter for the file
$/ = " .";
# the follow statement will create an error log of all error messages in log and save it
# to a file named errorlog.txt
while(<FH>)
{
push (@msgarray, $_);
}
if ($outputtype == 1)
{
$outputfile="errorlog.txt";
open(OUTPUT,">>$outputfile");
$errorcount=0;
$errortarget="ERROR";
print OUTPUT "-----------Error Log-----------\n";
for ($i=0;$i<@msgarray;$i++)
{
if ($msgarray[$i] =~ /^$errortarget/)
{
print OUTPUT "$msgarray[$i]\n";
# print OUTPUT "next code is: \n";
$errorcount++;
}
print OUTPUT "\nError Count : $errorcount\n";
close (OUTPUT);
}
}
答案 0 :(得分:3)
将换行符添加到分隔符。变化:
$/ = " .";
为:
$/ = " .\n";
如果您想删除分隔符,可以chomp
。
while(<FH>)
{
chomp;
push (@msgarray, $_);
}
答案 1 :(得分:2)
设置$/ = " ."
的问题在于,您读取的行将以该结束点结束,后面的行将以其后面的换行符开头。这意味着除了第一行之外,你的所有行都不会以"ERROR"
开头 - 它们将以"\nERROR"
开头,因此您的测试将始终失败
您希望了解代码中存在的其他一些问题。
您必须始终 use strict
和use warnings
,并使用my
声明所有变量尽可能接近其第一个使用点< / p>
您应始终使用具有open
三参数形式的词汇文件句柄。您还需要检查每个open
的状态,并将$!
放在die
字符串中,以便您知道 失败的原因。所以
open(FH,$filetoparse);
变为
open my $in_fh, '<', $filetoparse or die qq{Unable to open "$filetoparse" for input: $!};
最好逐行处理文本文件,除非您有充分的理由将它们全部读入内存 - 例如,如果您需要对数据进行多次传递,或者您需要随机访问对内容而不是线性处理它们。
值得注意的是,而不是写
while ( <$in_fh> ) {
push @msgarray, $_;
}
你可以说
@msgarray = <$in_fh>;
具有完全相同的结果
通常更好地迭代数组的内容而不是其索引。而不是
for ( my $i = 0; $i < @msgarray; ++$i ) {
# Do stuff with $msgarray[$i];
}
你可以写
for my $message ( @msgarray ) {
# Do stuff with $message;
}
这是重写代码,用于演示这些要点
open my $in_fh, '<', $filetoparse
or die qq{Unable to open "$filetoparse" for input: $!};
{
if ( $outputtype == 1 ) {
my $outputfile = 'errorlog.txt';
my $errorcount = 0;
my $errortarget = 'ERROR';
open my $out_fh, '>>', $outputfile
or die qq{Unable to open "$outputfile" for output: $!};
print $out_fh "-----------Error Log-----------\n";
while ( <$in_fh> ) {
next unless /^\Q$errortarget/;
s/\s*\.\s*\z//; # Remove trailing detail
print $out_fh "$_\n";
++$errorcount;
}
print $out_fh "\nError Count : $errorcount\n";
close ($out_fh) or die $!;
}
}
答案 2 :(得分:0)
文件句柄OUTPUT
在for
循环中关闭,您在关闭后每次迭代都会访问该循环。将它移到循环外面并尝试