用于Tomcat错误日志的正则表达式
考虑一下下面这个Tomcat日志的结构:
[06/Feb/2013:15:25:27 +0000] [Thread-10] DEBUG xxx.yyy.xxx.yyy.xxx.yyy.BlahBlahClass - Reloading blah configuration: /somepath/xxx.yyy
[06/Feb/2013:15:25:27 +0000] [Thread-11] ERROR xxx.yyy.xxx.yyy.xxx.yyy.BlahBlahClass2 - [xxx.yyy] - Could not find the somethinh
[06/Feb/2013:15:25:27 +0000] [Thread-12] ERROR xxx.yyy.xxx.yyy.xxx.yyy - error handling product : xxx.yyy don't know where it is
xxx.yyy.IOException: Could not find the feed with id [thisisfeedname_13601429613239870] in the feed repository or as a what?
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:57)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:65)
at xxx.yyy.xxx.yyy.xxx.yyy.flush(xxx.yyy:294)
at xxx.yyy.xxx.yyy.DelayedLogger$xxx.yyy(Unknown Source)
Caused by: xxx.yyy.FileNotFoundException: /path/to/feeds/xxx.yyy (No such file or directory)
at xxx.yyy.xxx.yyy(Native Method)
at xxx.yyy.FileInputStream.<init>(xxx.yyy:120)
at xxx.yyy.xxx.yyy.xxx.yyy.parse(xxx.yyy:248)
at xxx.yyy.xxx.yyy$xxx.yyy(Unknown Source)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:41)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:13)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:54)
at xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:176)
at xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:151)
at xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:143)
at xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:127)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:63)
at xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy(xxx.yyy:43)
... 3 more
[06/Feb/2013:15:25:27 +0000] [Thread-13] INFO xxx.yyy.xxx.yyy.xxx.yyy - constructing a new CSV feed resource
[06/Feb/2013:15:25:27 +0000] [Thread-14] DEBUG xxx.yyy.xxx.yyy.xxx.yyy.xxx.yyy - number of feeds defined for the resource: 1
[06/Feb/2013:15:25:27 +0000] [Thread-15] INFO xxx.yyy.xxx.yyy.xxx.yyy - constructing a new CSV feed resource
这个日志包含一行报告,开头是一个用大括号括起来的时间戳,后面可以跟着一个堆栈跟踪信息。例如,Thread-12
后面有一个堆栈跟踪,而线程10到15则没有。
我想把每个日志事件转换成一个Python对象,这个对象包含时间戳、错误类型(比如ERROR
、INFO
等)、消息和可选的堆栈跟踪。我试过以下的正则表达式:
reg_str='^\[(.*?)\]\s+\[(.*?)\]\s+(\w+)\s*(.*)\s*$\s*(([^\[].*?$)*)'
reg=re.compile(reg_str, re.MULTILINE)
可惜,每当有堆栈跟踪时,这个正则表达式就会贪婪地匹配到日志的结尾。
我该如何重写这个正则表达式,以正确匹配日志事件呢?
1 个回答
2
首先,把贪婪的部分改成非贪婪的;)
^\[(.*?)\]\s+\[(.*?)\]\s+(\w+)\s*(.*?)\s*$\s*(([^\[].*?$)*)
^
这里有一个Rubular链接。
不过你可以在这个链接里看到,正则表达式的其他部分有问题。首先,你需要把最后的 \s*
放到括号里面,因为可选的行可能会有缩进。其次,你需要用负向前瞻,而不是用否定字符类,这个原因可能会让解释变得复杂(但如果你想的话,我可以在评论里解释)。像这样:
^\[(.*?)\]\s+\[(.*?)\]\s+(\w+)\s*(.*?)\s*$((\s*(?!\[).*?$)*)
^^^^^^^^^^^
这里有另一个Rubular链接。
最后,那个最后的捕获组其实没什么用,所以……
^\[(.*?)\]\s+\[(.*?)\]\s+(\w+)\s*(.*?)\s*$((?:\s*(?!\[).*?$)*)
^^
这里是最终的Rubular链接。