多行分组并使用正则表达式进行搜索
好吧,正则表达式向导。我希望能够搜索我的日志文件,并找到其中包含"错误"一词的所有会话,然后返回整个会话日志条目。
我知道我可以使用字符串/数组来执行此操作,但是我想学习如何使用Regex进行操作,但这是问题所在。如果我决定使用Regex进行此操作,我是否会遇到一两个问题? ; 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 [email protected] Subject: test 1 Login name is [email protected] 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 [email protected] Subject: Lorem Update 08/27/2008 Login name is [email protected] 2008.08.27 08:07:58 (Wed)-------------End of Session------------------
解决方案
perl -ne'BEGIN {$ / =""}打印,如果/ error / i'<日志文件
Kyle的答案可能是最恰当的,但是如果我们将所有内容都放在一个字符串中并且想要使用单个正则表达式,则可以使用以下(经过测试的)解决方案:
(第二次更新:修复了一点,现在比以往任何时候都更易读;-)
my $re = qr{ ( # capture in (?: (?!\n\n). # Any character that's not at a paragraph break )* # repeated error (?: (?!\n\n). )* ) }msxi; while ($s =~ m/$re/g){ print "''\n"; }
丑陋,但我们要了。
就像最后一个家伙说的那样,从命令行运行perl即可。因此,将从命令行awk进行操作:awk'/-会话开始-/ {text =""; gotError = 0; } / Error / {gotError = 1;} /-会话结束-/ {if(gotError){print text}} {text = text" \ n" $ 0}'logFileName.txt
基本上,在" -Start of Session-"的行上开始记录,在" Error"的行上设置标志,并在" -Session of-End"上有条件地输出。
或者将其放入errorLogParser.awk中:
/-Start of Session-/{ text=""; gotError=0; } /Error/{ gotError=1; } /-End of Session-/{ if(gotError) { print text } } { text=text "\n"Error:.+}
...并像这样调用:awk -f errorLineParser.awk logFileName.txt
使用perl正则表达式引擎,简单的正则表达式
(?ms)^Error:[^\r\n]+$
根据quickrex来完成技巧。
(如果使用Java正则表达式引擎,则需要另一个正则表达式:
Error:\s*(\S.+)
)
具有捕获组的正则表达式将仅允许重定向错误消息,而不能重定向" Error"本身,如下所示:
/(?:[^\n\r]|\r?\n(?!\r|\n))*?Error:(?:[^\n\r]|\r?\n(?!\r|\n))*/g
组n1仅捕获"错误:"之后的内容
无论如何,对于正则表达式而言,请参阅regular-Expressions.info教程,这是该技术的一流介绍。
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
这利用了条目之间的空白行。它适用于Unix和Windows换行符。如果需要,我们可以用几乎所有其他内容替换中间的文本" Error:"。
如果我们想了解或者使用这些解决方案中的任何一种,我强烈建议我们下载Regex Coach,它可以构建和测试正则表达式
我要做的是将整个日志运行到一个字符串中,然后逐行浏览并将每行添加到第三个变量,直到该行包含" --Session End--"。然后,我也将该行添加到第3个var中,然后在第3个var中搜索单词" error"。如果包含它,则将第3个变量添加到第四个变量,然后清除第3个变量,并通过下一行的日志开始通过变量返回。
看起来像这样:
##代码##事实证明,当正则表达式不合适时,它确实可以成为实施的负担。有点像用螺丝刀代替锤子。这样就可以完成工作,但是要花很长时间,弄坏螺丝刀,并可能在此过程中伤害我们。
有时,当只有Vim可用时(当时我还没有掌握的sed,awk),我做了类似的事情:
通过vim,我已将会话开始/会话结束到单个行之间的所有行连接在一起:
- 首先将所有行尾替换为某些特定的char:%s:$:#
- 然后将double输入到其他分隔符中::%s:#\ n#\ n:#\ r @ \ r
- 加入行::%s:#\ n:#
- 仅显示以下行:Error::v / [Ee] rror / d
- 将行拆分为原始格式::%s:#:\ r
高温超导