如何解析 perl 中的特定行?
How to parse specific lines in perl?
我有来自应用程序服务器的日志,我需要获取带有 "E" 标记或 "W" 的行,如果标记行之后有一行,我也需要获取它。
我试着想出一个脚本:
#!/usr/bin/perl
use strict;
use warnings;
my $msg;
my $line;
my $line2;
main(@ARGV);
sub rec {
#$msg= $line;
print $line;
while ( $line2 = <FH>) {
if ( $line2 !~ m/^\[/ ){
#$msg = $msg.$line2;
print $line2;
} else {
if($line2 =~ m/ E | W /) { rec(); }
last;
}
}
#print $msg;
}
sub main {
open(FH,'SystemOut_15.02.05_17.00.02.log') or die "Error openong file : $!";
while ( $line = <FH>) {
if($line =~ m/ E | W / and $line =~ m/^\[/){
rec();
}
}
close FH;
}
提前致谢。
日志样本:
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
*********************************************************** Start Server *******************************
0000003a JDBCException O OK
0000003a JDBCException O OK
********************************************************** End Server *******************************
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
我需要得到什么:
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
忽略开始和停止之间的行的一种有效方法是使用 ysth 指示的触发器;其他(弱)方法:
open(my $fh, '<', 'test2.log') or die "Error opening file : $!";
my $match = 0;
while ( my $line = <$fh> ) {
if ( $line =~ /^\*+/ ){
$match = 0; ## initialize match if line start with star
}
if ( $line =~ /^\[/ ) {
$match = $line =~ m/ E | W /;
}
print $line if $match;
}
close $fh;
很简单;您只需要跟踪您当前是否在匹配的多行记录中,并使用 flipflop operator (scalar context ..
) 排除 Start/End 服务器范围的行:
open(my $fh, '<', 'SystemOut_15.02.05_17.00.02.log') or die "Error opening file : $!";
my $match = 0;
while ( my $line = <$fh> ) {
unless ( $line =~ /^\*+ Start Server \*+$/ .. $line =~ /^\*+ End Server \*+$/ ) {
if ( $line =~ /^\[/ ) {
$match = $line =~ m/ E | W /;
}
print $line if $match;
}
}
close $fh;
您可能会受益于阅读 Watching Logs and Tail following web server.
上 POE::Wheel::FollowTail 好人提供的优秀代码示例
由于您的日志文件有多行记录,您的任务并不像最初猜测的那么简单。您需要创建一个模式来识别记录的开头([2/5/15 14:55:18:025 UTC] 0000003a JDBCException O ),我会测试 DateTime String 后跟 HEX 数字和括号内的 JDBCException 可以是一个安全的选择,如果所有以空格开头的行都在继续相同的记录(这将需要测试)。
您可能应该只捕获每条记录并将它们发送给另一个事件处理,或者甚至发送每条记录以使用 POE::Wheel::Run 之类的东西在子进程上处理,假设您需要同时具有词法解析器(log taillor)和语义解析器(解释日志记录)。
我不知道多行 filter, but you'd probably benefit from reading the code of POE::Filter::RecordBlock。
我有来自应用程序服务器的日志,我需要获取带有 "E" 标记或 "W" 的行,如果标记行之后有一行,我也需要获取它。
我试着想出一个脚本:
#!/usr/bin/perl
use strict;
use warnings;
my $msg;
my $line;
my $line2;
main(@ARGV);
sub rec {
#$msg= $line;
print $line;
while ( $line2 = <FH>) {
if ( $line2 !~ m/^\[/ ){
#$msg = $msg.$line2;
print $line2;
} else {
if($line2 =~ m/ E | W /) { rec(); }
last;
}
}
#print $msg;
}
sub main {
open(FH,'SystemOut_15.02.05_17.00.02.log') or die "Error openong file : $!";
while ( $line = <FH>) {
if($line =~ m/ E | W / and $line =~ m/^\[/){
rec();
}
}
close FH;
}
提前致谢。
日志样本:
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
*********************************************************** Start Server *******************************
0000003a JDBCException O OK
0000003a JDBCException O OK
********************************************************** End Server *******************************
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException O OK
我需要得到什么:
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, S
QLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
[2/5/15 14:55:18:025 UTC] 0000003a JDBCException E org.hibernate.util.JDBCExceptionReporter logExceptions SQL Error: 17006, SQLState: null
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
org.hibernate.util.JDBCExceptionReporter
忽略开始和停止之间的行的一种有效方法是使用 ysth 指示的触发器;其他(弱)方法:
open(my $fh, '<', 'test2.log') or die "Error opening file : $!";
my $match = 0;
while ( my $line = <$fh> ) {
if ( $line =~ /^\*+/ ){
$match = 0; ## initialize match if line start with star
}
if ( $line =~ /^\[/ ) {
$match = $line =~ m/ E | W /;
}
print $line if $match;
}
close $fh;
很简单;您只需要跟踪您当前是否在匹配的多行记录中,并使用 flipflop operator (scalar context ..
) 排除 Start/End 服务器范围的行:
open(my $fh, '<', 'SystemOut_15.02.05_17.00.02.log') or die "Error opening file : $!";
my $match = 0;
while ( my $line = <$fh> ) {
unless ( $line =~ /^\*+ Start Server \*+$/ .. $line =~ /^\*+ End Server \*+$/ ) {
if ( $line =~ /^\[/ ) {
$match = $line =~ m/ E | W /;
}
print $line if $match;
}
}
close $fh;
您可能会受益于阅读 Watching Logs and Tail following web server.
上 POE::Wheel::FollowTail 好人提供的优秀代码示例由于您的日志文件有多行记录,您的任务并不像最初猜测的那么简单。您需要创建一个模式来识别记录的开头([2/5/15 14:55:18:025 UTC] 0000003a JDBCException O ),我会测试 DateTime String 后跟 HEX 数字和括号内的 JDBCException 可以是一个安全的选择,如果所有以空格开头的行都在继续相同的记录(这将需要测试)。
您可能应该只捕获每条记录并将它们发送给另一个事件处理,或者甚至发送每条记录以使用 POE::Wheel::Run 之类的东西在子进程上处理,假设您需要同时具有词法解析器(log taillor)和语义解析器(解释日志记录)。
我不知道多行 filter, but you'd probably benefit from reading the code of POE::Filter::RecordBlock。