数据平台的源数据,很大部分来源于日志。一说到日志扫描和解析,不可避免就涉及到正则表达式匹配,没有了正则表达式,日志的匹配就很难做到自动化和高效。
在日志匹配中,有种常见的匹配情形,叫“不包含”。就是说,我们希望这条日志,在匹配某个通用特征的情况下,又不包含某个特征,例如说:
A pig is running.
我们希望匹配到所有带pig的日志,但是我们不希望匹配到pig带running的日志。而且我们不希望改程序,扫描或者解析2次,我们希望一次匹配就能匹配出,带pig而不带running的日志。
这种情况,貌似需要编程解决,但是强大而无所不能的正则表达式,早就考虑到了这种情况,并且优雅的解决了。这个正则表达式技术,就叫:
否定式前瞻
具体的否定式前瞻的解释,可以看看这篇图文并茂的文章,我相信没有那篇文章比它解释得更加通俗易懂了。
我要在这里强调的只是两点:
1. 上面的文章,给出的正则表达式语法不是Java的,所以你照样copy的话,到了Java是不生效的。这里我翻译一下,给出Java个版本的否定式前瞻正则表达式,注意它同样适用于Python。
匹配淘宝item的url,但是不带ali_trackid
http://item.taobao.com/item.htm\?id=[0-9](?!.*ali_trackid).*
2. 这个表达式,重点是括号里面的(.*)和括号外面的.*。不能够写成 .*(?!.*ali_trackid).*。具体原因,参考文章中有详细的说明。
最后,补补正则表达式中,非捕获组的基本概念。
最后解释一下非捕获组的语法。我们都知道,Java和Python中,()表示捕获组,但是一旦是(?),就表示非捕获组了。具体解释可以看:
http://www.blogjava.net/sdyjmc/archive/2010/01/06/308391.html
前对应右,后对应坐,前瞻后顾,正则表达式之美也~~~其中,否定式前瞻的应用最为实用,日志扫描中,经常会用到,请细心体会研究。