2012-08-02 74 views
0

我是python新手。我试图编写一个快速而脏的python脚本来查找某些字符串日志文件并从该行中提取某些信息。在日志文件中的行看起来像这样python搜索文件和使用正则表达式解析

2012-08-01 13:36:40,449 [PDispatcher: ] ERROR Fatal error DEF_CON encountered. Shutting down 
2012-08-01 14:17:10,749 [PDispatcher: ] INFO Package 1900034442 Queued for clearance. 
2012-08-01 14:23:06,998 [PDispatcher: ] ERROR Exception occurred attempting to lookup prod id 90000142 

我有一个函数,其中输入参数将是一个文件名和模式数组寻找。目前我可以找到文件中包含一个或多个指定模式的所有行(尽管不知道它是否是最有效的方式),并且我可以提取行号和行。

def searchLogs(fn, searchPatterns): 
    res = [] 
    with open(fn) as f: 
     for lineNo, line in enumerate(f, 1): 
      #check if pattern strings exist in line 
      for sPattern in searchPatterns: 
       if sPattern in line: 
        fountItem = [fn, pattern, lineNo, line] 
        res.append(fountItem) 
    return res 

searchLogs("c:\temp\app.log", ["ERROR", "DEF_CON"]) #this should return 3 elements based on the above log snipped (2 for the first line and 1 for the third line) 

我想要做的还是提取日期和时间,同时搜索。因此,我正在考虑将搜索模式修改为具有分组功能的正则表达式字符串,以便搜索和提取日期。只有一个问题,我不知道如何在Python中做到这一点...任何帮助,将不胜感激。

编辑(解决方案):从塞巴斯蒂安帮助和乔尔提供的链接,我想出了这个解决方案:

def search_logs(fn, searchPatterns): 
    res = [] 
    with open(fn) as f: 
     for lineNo, line in enumerate(f, 1): 
      #check if pattern strings exist in line 
      for sPattern in searchPatterns: 
       #crude reg ex to match pattern and if matched, 'group' timestamp 
       rex = r'^(.+) \[.*' + pattern 
       ms = re.match(rex, line) 
       if ms: 
        time = ms.group(1) 
        item = Structs.MatchedItem(fn, pattern, lineNo, line, time) 
        res.append(item) 
    return res 

search_logs("c:\temp\app.log", ["ERROR", "DEF_CON"]) #this should return 3 elements based on the above log snipped (2 for the first line and 1 for the third line) 
+2

http://docs.python.org/howto/regex.html – 2012-08-02 03:55:46

+0

你应该改善你的问题,缺乏一些研究的问题在堆栈溢出中被认为是粗鲁的。 – 2012-08-02 03:59:49

+0

我的道歉......这是我写的第一个python代码,正如我所说的那样,它是一个快速而肮脏的脚本,意味着可以短期解决监控问题。 – mike01010 2012-08-02 04:05:54

回答

1

有两个部分:

  • 提取日期时间字符串
  • 将其解析为日期时间对象

对于以后你可以使用datetime.strptime() function

try: 
    dt = datetime.strptime(line.split(" [", 1)[0], "%Y-%m-%d %H:%M:%S,%f") 
except ValueError: 
    dt = None 

前者取决于如何定期您的日志文件,并希望该解决方案是如何例如快速稳健,line.split(" [", 1)[0]是快,但很脆弱。更强大的解决方案是:

' '.join(line.split(None, 2)[:2]) 

但它可能会更慢。

+0

在看林提供Joel,我想我可以在一行中使用正则表达式来搜索和“去除”。我还没有弄清楚它..但我认为我可以生成一个表达式,其中包含日期/时间模式+(模式1 | patern2),我应该能够匹配,并与适当的分组,提取日期...如果不是,我会尝试一下,回落一下你的建议。 – mike01010 2012-08-02 04:20:04

+1

@ mike01010:这里没有必要使用正则表达式。 'strptime()'做你需要的所有验证。您可以使用我的第二个建议('''.join(...)')来提取日期时间部分:它始终适用于正确的日期时间,其余部分由'strptime()'处理。 – jfs 2012-08-03 03:55:49

+0

再次感谢塞巴斯蒂安。暗暗的建议是非常好的知道,并有帮助。 – mike01010 2012-08-06 16:26:00

1

这是你的正则表达式。我已经测试了正则表达式,但不是全部的代码

def searchLogs(fn, searchPatterns): 
    res = [] 
    with open(fn) as f: 
     for lineNo, line in enumerate(f, 1): 
      #check if pattern strings exist in line 
      for sPattern in searchPatterns: 
       if sPattern in line: 
        date = re.search(r'(19|20)\d{2}-(0[1-9]|[12])-(0[1-9]|[12][0-9]|3[01])',line).group() 
        time = re.search(r'\b([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]),[0-9][0-9][0-9]',line).group() 
        fountItem = (fn, pattern, lineNo, date, time, line) # prefer a tuple over list 
        res.append(fountItem) 
    return res 

PS:RE比较总是在错误的地方痛。让我知道你是否需要解释。 :)

+0

谢谢anothony,根据以前的回复,我能够想出一个不太“安全”的解决方案。我编辑了我的原始帖子以提供该解决方案。 – mike01010 2012-08-02 05:46:44