【问题标题】:How to parse specific lines in perl?如何解析perl中的特定行?
【发布时间】:2015-04-06 18:34:53
【问题描述】:

我有来自应用服务器的日志,我需要获取带有“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;

【问题讨论】:

  • 表示单行的行(找到后停止查找)?你能解释一下你的代码是做什么的吗?它似乎比你对你想要的描述复杂得多
  • 您能否提供输入样本以及您希望提取的内容?
  • @ysth/ @Sobrique :不,它会查找所有出现的模式
  • 所以你想要的不仅仅是下一行,而是每场比赛后的任何非 [ 行?

标签: perl parsing logging


【解决方案1】:

很简单;您只需要跟踪您当前是否在匹配的多行记录中,并使用flipflop operator (scalar context ..) 排除开始/结束服务器范围的行:

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;

【讨论】:

  • 您好,感谢您的代码,但如果它以以下形式开头,则不予考虑:code[2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org。 hibernate.util.JDBCExceptionReporter logExceptions SQL 错误:17006,S QLState:空 *********************************** ************************ 启动服务器 ************************ ******* 0000003a JDBCException O OK 0000003a JDBCException O OK [2/5/15 14:55:18:025 UTC] 0000003a JDBCException W org.hibernate.util.JDBCExceptionReporter logExceptions SQL 错误:17006,SQLState:空code
  • 我不确定你的意思;你能把它放在你的示例输入(和输出,如果它应该被包括在内?)
  • 我把它;现在我必须忽略 Start 和 Stop 之间的行,并在其他行中采用相同的逻辑。
  • 感谢您的触发器;这对我来说是新的,我也用 if 来做
【解决方案2】:

您可能会从Watching LogsTail following web server 上的 POE::Wheel::FollowTail 人员提供的优秀代码示例中受益。

由于您的日志文件包含多行记录,因此您的任务并不像最初猜测的那么简单。您需要创建一个模式来识别记录的开头([2/5/15 14:55:18:025 UTC] 0000003a JDBCException O ),我会测试 DateTime String后跟 HEX 数字和括号内的 JDBCException 可能是一个安全的选择,如果所有以空格开头的行都继续相同的记录(这需要测试)。

您可能应该只捕获每条记录并将它们发送给另一个事件处理,或者甚至使用POE::Wheel::Run 之类的东西发送每条记录以在子进程上处理,假设您需要同时拥有一个词法解析器(日志裁缝)和语义解析器(解释日志记录)。

我不知道有多行 filter,但您可能会从阅读 POE::Filter::RecordBlock 的代码中受益。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 2017-03-25
    • 2010-12-05
    • 1970-01-01
    相关资源
    最近更新 更多