Regex 使用Perl如何读入文件并解析日志以查找错误日志并输出到log.txt文件
我试图使用Perl创建一个程序,该程序将读取40000多行长文件的数据,并解析每条消息,从中提取错误消息 我使用的数据示例如下所示:Regex 使用Perl如何读入文件并解析日志以查找错误日志并输出到log.txt文件,regex,perl,Regex,Perl,我试图使用Perl创建一个程序,该程序将读取40000多行长文件的数据,并解析每条消息,从中提取错误消息 我使用的数据示例如下所示: --------All Messages--------- SUCCESS: data transferred successfully . SUCCESS: data transferred successfully . SUCCESS: data transferred successfully . ERROR: there was an error tran
--------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根据结果,它以成功或错误开始
2所有消息将以结尾
下面是我编写的代码,但由于某些原因,我似乎无法调试它。非常感谢您的帮助
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);
}
}
将换行符添加到分隔符中。更改:
$/ = " .";
致:
如果你想删除分隔符,你可以选择
将换行符添加到分隔符中。更改:
$/ = " .";
致:
如果你想删除分隔符,你可以选择
文件句柄输出在for循环中关闭,您在关闭后每次迭代都会访问该for循环。将其移到循环外并尝试它文件句柄输出将在for循环内关闭,关闭后您将在每次迭代中访问该for循环。将其移到循环之外,然后尝试设置$/=。您读取的行将以该结束点结束,下一行将以其后面的换行符开始。这意味着除了第一行之外,您的所有行都不会以错误开头-它们将以\n错误开头,因此测试将始终失败
您的代码还有一些其他问题需要了解
您必须始终使用strict和use warnings,并使用my声明所有变量,尽可能接近它们的第一个使用点
您应该始终将词汇文件句柄与open的三参数形式一起使用。您还需要检查每个打开和放置$的状态!这样你就知道它为什么失败了。所以
open(FH,$filetoparse);
变成
open my $in_fh, '<', $filetoparse or die qq{Unable to open "$filetoparse" for input: $!};
下面是对代码的重写,演示了这些要点
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 $!;
}
}
设置$/=的问题。您读取的行将以该结束点结束,下一行将以其后面的换行符开始。这意味着除了第一行之外,您的所有行都不会以错误开头-它们将以\n错误开头,因此测试将始终失败
您的代码还有一些其他问题需要了解
您必须始终使用strict和use warnings,并使用my声明所有变量,尽可能接近它们的第一个使用点
您应该始终将词汇文件句柄与open的三参数形式一起使用。您还需要检查每个打开和放置$的状态!这样你就知道它为什么失败了。所以
open(FH,$filetoparse);
变成
open my $in_fh, '<', $filetoparse or die qq{Unable to open "$filetoparse" for input: $!};
下面是对代码的重写,演示了这些要点
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 $!;
}
}
如果它是一个40k行的文件,为什么要在内存中读取它呢?我猜如果您将测试更改为$msgarray[$I]=~/^$errortarget/m,这将允许在记录的前导换行符后匹配^s,那么代码将正常工作。发布代码后请不要修复代码。它将其他人的评论和解决方案置于上下文之外。对不起,博罗丁,使用这个网站还是比较新的。我将更好地继续遵循SOP。如果它是一个40k行的文件,为什么要在内存中全部读取它?我猜如果您将测试更改为$msgarray[$I]=~/^$errortarget/m,这将允许^s与记录中的前导换行符匹配,那么代码将正常工作。请不要在发布后修复代码。它将其他人的评论和解决方案置于上下文之外。对不起,博罗丁,使用这个网站还是比较新的。我会继续跟进SOP的。谢谢你的帮助!你能告诉我为什么我的代码不起作用吗?不管是哪一行有错误还是什么?我知道我的代码很糟糕,这就是我在当地大学学习perl入门课程的方式,我很好奇我的代码在哪里失败了。如果你能帮忙,谢谢你@Drubs1181:正如我说过的几次,问题是您设置了$/=。因此,每条记录的开头都有一个换行符,/^ERROR/不匹配。这非常有帮助!你能告诉我为什么我的代码不起作用吗?不管是哪一行有错误还是什么?我知道我的代码很糟糕,这就是我在当地大学学习perl入门课程的方式,我很好奇我的代码在哪里失败了。如果你能帮忙,谢谢你@Drubs1181:正如我说过的几次,问题是您设置了$/=。因此,每条记录的开头都有一个换行符,/^ERROR/不匹配,这是不正确的。结束在while和for循环之外,这是不正确的。闭合在while和for循环之外
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 $!;
}
}