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