多行组并使用Regex进行搜索

时间:2008-09-30 19:58:43

标签: regex

好的,正则表达式的巫师。我希望能够搜索我的日志文件并找到其中包含“错误”一词的任何会话,然后返回整个会话日志条目。

我知道我可以使用字符串/数组来完成此操作,但我想学习如何使用Regex,但这是问题所在。如果我决定使用正则表达式执行此操作have one or two problems? ; O)

这是日志:

PS:我正在使用perl Regex引擎。

注意:我认为我无法在Regex中完成此操作。换句话说,我现在有两个问题。 ; o)我已经尝试了下面的解决方案,但是,由于我通过声明我使用的是Perl引擎而混淆了这个问题,许多答案都在Perl中(在我的情况下不能使用)。不过我在下面发布了我的解决方案。


2008.08.27 08:04:21 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Sending stdin.txt to foo@bar.com  
Subject: test 1  
Login name is foo@bar.com  
The SMTP server does not require AUTH LOGIN.  
Are you sure server supports AUTH?  
The SMTP server does not like the sender name.  
Have you set your mail address correctly?  
2008.08.27 08:04:24 (Wed)-------------End of Session------------------  

2008.08.27 08:05:56 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Error: Wait a bit (possible timeout).  
SMTP server error  
Error: Not a socket.  
Error: Not a socket.  
2008.08.27 08:06:26 (Wed)-------------End of Session------------------  

2008.08.27 08:07:58 (Wed)------------Start of Session-----------------  
Blat v2.6.2 w/GSS encryption (build : Feb 25 2007 12:06:19)  
Sending stdin.txt to foo@bar.com  
Subject: Lorem Update 08/27/2008  
Login name is foo@bar.com  
2008.08.27 08:07:58 (Wed)-------------End of Session------------------  

8 个答案:

答案 0 :(得分:7)

Kyle的回答可能是最有意义的,但是如果你把它全部放在一个字符串中并且想要使用一个正则表达式,那么这是一个(测试的)解决方案:

第二次更新:修复了一下,现在更具可读性了; - )

my $re = qr{
        (           # capture in $1
         (?:
          (?!\n\n). # Any character that's not at a paragraph break
         )*        # repeated
         error
         (?:
          (?!\n\n).
         )*
        )
}msxi;


while ($s =~ m/$re/g){
    print "'$1'\n";
}

丑陋,但你要求它。

答案 1 :(得分:6)

看起来您的会话是由空行分隔的(除了开始/结束标记)。如果是这种情况,这是一个单线:

perl -ne 'BEGIN{$/=""} print if /error/i' < logfile

答案 2 :(得分:1)

/(?:[^\n\r]|\r?\n(?!\r|\n))*?Error:(?:[^\n\r]|\r?\n(?!\r|\n))*/g

这利用了条目之间的空白行。它适用于unix和windows换行符。如果您愿意,可以将中间的文本“Error:”替换为几乎任何其他内容。

答案 3 :(得分:0)

像最后一个人说的那样,来自命令行的perl会起作用。所以将从命令行中唤醒:
awk '/-Start of Session-/ { text=""; gotError=0; } /Error/{gotError=1;}/-End of Session-/{ if(gotError) {print text}} { text=text "\n" $0}' logFileName.txt

基本上,在“-Start of Session-”的行上开始录制,在“Error”的行上设置一个标志,并在“-End of Session”的行上有条件地输出。

或者将其放入errorLogParser.awk:

/-Start of Session-/{
    text="";
    gotError=0;
}
/Error/{
    gotError=1;
}
/-End of Session-/{
    if(gotError)
    {
        print text
    }
}
{
    text=text "\n" $0
}
...并调用如下: awk -f errorLineParser.awk logFileName.txt

答案 4 :(得分:0)

使用perl regexp引擎,简单的正则表达式

Error:.+ 

按照quickrex进行操作。

(使用java regexp引擎,需要另一个正则表达式:

(?ms)^Error:[^\r\n]+$

带有捕获组的正则表达式只允许重定向错误消息而不是“错误”本身,如:

Error:\s*(\S.+)

组n°1仅捕获'错误:'

之后的内容

无论如何,对于regexp,请参阅regular-Expressions.info tutorial,这是该技术的一流介绍。

答案 5 :(得分:0)

如果您想了解或使用任何这些解决方案,我强烈建议您下载Regex Coach,这有助于您构建和测试正则表达式

答案 6 :(得分:0)

我所做的是将整个日志运行到一个字符串然后逐行进行并将每一行添加到第三个变量,直到该行包含“ - Session of Session--”。然后我将该行添加到第3个var中,然后在第3个var中搜索单词“error”。如果它包含它,我将第3个var添加到第4个,然后清除第3个var并开始返回var并使用下一行的日志。

看起来像这样:

str a b email gp lgf
lgf.getfile( "C:\blat\log.txt")
foreach a lgf
    if(find(a "--End of Session--")>-1)
        gp.from(gp "[]" a)
        if(find(gp "error" 0 1)>-1)
            gp.trim
            email.from(email gp "[]")
        gp=""
        continue
    gp.from(gp "[]" a)
email.trim

事实证明,当正则表达式不合适时,它可以真正成为熊猫。有点像使用螺丝刀而不是锤子。它会完成工作,但需要很长时间,打破螺丝刀,并可能在此过程中伤害到你。

答案 7 :(得分:0)

偶尔只有Vim可用(和sed,当时我没有掌握的awk),我做了类似的事情:

通过vim,我加入了所有线路 - 在您的情况下 - 会话开始/会话结束到单行:

  • 首先将所有行结尾替换为某个特定的字符

    :%S:$:#

  • 然后双人进入其他分隔符:

    :%S:#\ N#\ N:#\ r @ \ r

  • 加入专栏:

    :%S:#\ N:#

  • 仅显示错误行:

    :v / [Ee] rror / d

  • 将线条拆分为原始格式:

    :%S:#:\ r

HTH

相关问题