使用log4j语法考虑日志文件:
2014-02-10 08:44:53,295 ERROR com.comnany.some.class Message
message message message
2014-02-10 08:44:53,995 WARN com.comnany.some.class An irrelevant warn message...
2014-02-10 08:45:00,010 DEBUG com.comnany.some.class An irrelevant debug message...
我需要在perl中编写匹配器以匹配日志文件中的所有错误。匹配不仅必须包含其中包含ERROR的行,还必须包含所有行,直到(但不包括)下一个日志条目的开头。
任何人都可以提出正则表达式来执行此匹配(最好有解释)吗?
答案 0 :(得分:2)
试试这个正则表达式:
/(?P<date>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2},\d{1,3}\s+)ERROR\s+
(?P<class>.+?)\s+
(?P<message>.+?)(?=(?1)|$)/gsx
g: Search globally (don't return on first match).
s: Dot matches newline characters.
x: Spaces in the pattern are ignored.
答案 1 :(得分:0)
加载整个文件以查找多行日志条目是一个非常糟糕的主意。考虑日志文件的大小,现在必须将其全部加载到内存中并一次处理。 Perl历史上不太善于释放记忆......
更合理的方法是整个或从特定点处理日志,在循环中设置一个标记,检查每一行并添加它是否是新条目。
首先请注意,请考虑使用qr()运算符预编译正则表达式。这将为您节省几个周期,特别是当您迭代多行或以其他方式多次使用相同的正则表达式时。
关于我下面的代码的另一个注意事项,我喜欢使用label和next()语句,因为显式地连接到循环的下一次迭代会澄清代码的流程。
整体流程将是:
它可能看起来像这样:
my $log_entry_begin_regex = qr/(?P<date>\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2},\d{1,3}\s+)(FATAL|WARN|ERROR|INFO|DEBUG|TRACE)/;
my $found_error_flag;
open my $file, "<", $path_to_file;
LINE:
while ( my $line = <$file> ) {
# It's a new log entry line
if (($line, $error_level) =~ $log_entry_begin_regex ) {
if ( $error_level eq 'ERROR' ) {
$found_error_flag = 1;
print $line
next LINE;
} else {
$found_error_flag = 0;
next LINE;
}
} elsif ($found_error_flag ) {
print $line;
}
}