2011-04-28 64 views
1

我需要分析一些日誌文件,它看起來像下面,我想找回3個部分的數據,Python正則表達式來獲取文件名的長路徑

  1. 時間目錄
  2. 部分,在這種情況下,它將是輸入文件中的ABC和DEF。
  3. 在這種情況下輸入文件中的文件名,即2C.013000000B.dat,20100722B.TXT,20100722D1-XYZ.TXT和2C.250B。

我使用這個正則表達式,但它沒能得到第三部分。

(\d\d:\d\d:\d\d).*(ABC|DEF).*\\(\d\w\.?\w\..*)\soutput.* 

任何建議將不勝感激。

08:38:36 TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-ABC\2C.013000000B.dat output file=c:\local\project1\data\2C.013000000B.dat.ext 
06:40:37 TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-ABC\20100722B.TXT output file=c:\local\project1\data\20100722B.TXT.ext 
06:40:39 TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-DEF\20100722D1-XYZ.TXT output file=c:\local\project1\data\20100722D1-YFP.TXT.ext 
06:40:42 TestModule - [INFO]result success !! ftp_site=ftp.test.com file_dir=CPY input file=\root\level1\level2-DEF\2C.250B output file=c:\local\project1\data\2C.250B.ext 

BR

愛德華

+0

非常感謝你。 – user729544 2011-04-28 15:15:11

回答

2

正則表達式非常擅長解決像這樣的問題 - 即解析日誌文件記錄。 MarcoS的答案很好地解決了你的直接問題。然而,另一種方法是編寫一個(可重用)泛化函數,將日誌文件記錄分解爲各種組件,並返回包含所有這些解析組件的匹配對象。一旦分解,測試可以很容易地應用到組件部分以檢查各種需求(例如輸入文件路徑必須以ABCDEF結束)。這裏是一個具有這樣一個功能的python腳本:decomposeLogEntry()並演示瞭如何使用它的手來解決問題:

import re 
def decomposeLogEntry(text): 
    r""" Decompose log file entry into its various components. 

    If text is a valid log entry, return regex match object of 
    log entry components strings. Otherwise return None.""" 
    return re.match(r""" 
     # Decompose log file entry into its various components. 
     ^       # Anchor to start of string 
     (?P<time>\d\d:\d\d:\d\d)  # Capture: time 
     \s+ 
     (?P<modname>\w+?)   # Capture module name 
     \s-\s\[ 
     (?P<msgtype>[^]]+)   # Capture message type 
     \] 
     (?P<message>[^!]+)   # Capture message text 
     !!\sftp_site= 
     (?P<ftpsite>\S+?)   # Capture ftp URL 
     \sfile_dir= 
     (?P<filedir>\S+?)   # Capture file directory? 
     \sinput\sfile= 
     (?P<infile>     # Capture input path and filename 
      (?P<infilepath>\S+)\\  # Capture input file path 
      (?P<infilename>[^\s\\]+) # Capture input file filename 
     ) 
     \soutput\sfile= 
     (?P<outfile>     # Capture input path and filename 
      (?P<outfilepath>\S+)\\  # Capture output file path 
      (?P<outfilename>[^\s\\]+) # Capture output file filename 
     ) 
     \s*       # Optional whitespace at end. 
     $       # Anchor to end of string 
     """, text, re.IGNORECASE | re.VERBOSE) 

# Demonstrate decomposeLogEntry function. Print components of all log entries. 
f=open("testdata.log") 
mcnt = 0 
for line in f: 
    # Decompose this line into its components. 
    m = decomposeLogEntry(line) 
    if m: 
     mcnt += 1 
     print "Match number %d" % (mcnt) 
     print " Time:    %s" % m.group("time") 
     print " Module name:  %s" % m.group("modname") 
     print " Message type:  %s" % m.group("time") 
     print " Message:   %s" % m.group("message") 
     print " FTP site URL:  %s" % m.group("ftpsite") 
     print " Input file:  %s" % m.group("infile") 
     print " Input file path: %s" % m.group("infilepath") 
     print " Input file name: %s" % m.group("infilename") 
     print " Output file:  %s" % m.group("outfile") 
     print " Output file path: %s" % m.group("outfilepath") 
     print " Output file name: %s" % m.group("outfilename") 
     print "\n", 
f.close() 

# Next pick out only the desired data. 
f=open("testdata.log") 
mcnt = 0 
matches = [] 
for line in f: 
    # Decompose this line into its components. 
    m = decomposeLogEntry(line) 
    if m: 
     # See if this record meets desired requirements 
     if re.search(r"ABC$|DEF$", m.group("infilepath")): 
      matches.append(line) 
f.close() 
print "There were %d matching records" % len(matches) 

此功能不僅挑選出你有興趣,它的各個部分也驗證輸入並拒絕格式不正確的記錄。一旦寫入和調試完畢,該功能可以被其他需要分析日誌文件以滿足其他需求的程序重複使用。

下面是從腳本的輸出時,應用到您的測試數據:

r""" 
Match number 1 
    Time:    08:38:36 
    Module name:  TestModule 
    Message type:  08:38:36 
    Message:   result success 
    FTP site URL:  ftp.test.com 
    Input file:  \root\level1\level2-ABC\2C.013000000B.dat 
    Input file path: \root\level1\level2-ABC 
    Input file name: 2C.013000000B.dat 
    Output file:  c:\local\project1\data\2C.013000000B.dat.ext 
    Output file path: c:\local\project1\data 
    Output file name: 2C.013000000B.dat.ext 

Match number 2 
    Time:    06:40:37 
    Module name:  TestModule 
    Message type:  06:40:37 
    Message:   result success 
    FTP site URL:  ftp.test.com 
    Input file:  \root\level1\level2-ABC\20100722B.TXT 
    Input file path: \root\level1\level2-ABC 
    Input file name: 20100722B.TXT 
    Output file:  c:\local\project1\data\20100722B.TXT.ext 
    Output file path: c:\local\project1\data 
    Output file name: 20100722B.TXT.ext 

Match number 3 
    Time:    06:40:39 
    Module name:  TestModule 
    Message type:  06:40:39 
    Message:   result success 
    FTP site URL:  ftp.test.com 
    Input file:  \root\level1\level2-DEF\20100722D1-XYZ.TXT 
    Input file path: \root\level1\level2-DEF 
    Input file name: 20100722D1-XYZ.TXT 
    Output file:  c:\local\project1\data\20100722D1-YFP.TXT.ext 
    Output file path: c:\local\project1\data 
    Output file name: 20100722D1-YFP.TXT.ext 

Match number 4 
    Time:    06:40:42 
    Module name:  TestModule 
    Message type:  06:40:42 
    Message:   result success 
    FTP site URL:  ftp.test.com 
    Input file:  \root\level1\level2-DEF\2C.250B 
    Input file path: \root\level1\level2-DEF 
    Input file name: 2C.250B 
    Output file:  c:\local\project1\data\2C.250B.ext 
    Output file path: c:\local\project1\data 
    Output file name: 2C.250B.ext 

There were 4 matching records 
""" 
+0

謝謝,我會記住。 – user729544 2011-04-28 23:59:09

1

如果使用正則表達式的工具,它將使你的生活進行故障排除正則表達式輕鬆了許多。嘗試this free one - 有可能是更好的,但這很好。你可以在那裏粘貼你的日誌文件,並且一次嘗試一下你的正則表達式,它會實時地突出顯示匹配。

+0

謝謝,我確實先試過這個快遞生產商,但是我得到了這個結果,這就是我爲什麼要問這裏的原因。非常感謝你。 win32上的Python 2.7.1(r271:86832,Nov 27 2010,18:30:46)win32 >>> import re >>> s1 = re.compile(' \\(\ d \ w \。?(P3 | TXT |))\ s',re.IGNORECASE) 回溯(最近呼叫最後一個): 文件「」 ,第1行,在 文件「c:\ python27 \ lib \ re.py」,第190行,編譯 return _compile(pattern,flags) 文件「c:\ python27 \ lib \ re.py」,行245,在_compile 引發錯誤,v#無效表達式 sre_constants.error:不平衡括號 – user729544 2011-04-28 16:09:40

+0

每當我有一個複雜的正則表達式不工作,我在嘗試一點時間...例如,我會開始w /第一部分瓦特/時間,一旦工作,添加更多等等,很容易以這種方式排除故障。 – 2011-04-28 17:01:01

1

爲什麼是正則表達式?

考慮使用split來獲取所有單詞。這會直接給你時間戳。然後檢查所有其他詞語,檢查它們中是否有=,在這種情況下再次分割它們,並且在那裏有很好的路徑和其他參數。標準Python路徑處理(os.path)將幫助您獲取文件夾和文件名。

當然,如果你的路徑名可能包含空格,這種方法會失敗,否則它絕對值得考慮。

+0

謝謝,我嘗試拆分,它的工作原理,但我仍然想知道正則表達式可以做到這一點。 – user729544 2011-04-28 15:43:48

+1

有些人遇到問題時,會想「我知道,我會用正則表達式」。現在他們有兩個問題。 – Wilduck 2011-04-28 18:27:23

1

你可以簡單地通過正常的字符串處理

f=open("file") 
for line in f: 
    date,b = line.split("input") 
    print "time: " , date.split()[0] 
    input_path = b.split("output")[0] 
    tokens=input_path.split("\\") 
    filename=tokens[-1] 
    directory=tokens[-2].split("-")[-1] 
    print filename, directory 
f.close() 
+0

謝謝你的作品,但我仍然想知道如何用正則表達式來完成這個。 – user729544 2011-04-28 15:42:44

2

採用分體式是一個好主意去做。如果你真的想要一個正則表達式,我會做這樣的:

(\d\d:\d\d:\d\d).*?input file=.*?(ABC|DEF)\\\\(.*?)\soutput 

測試它here

+0

我嘗試在我的程序,它使用Python 27,但它失敗 回溯(最近通話最後一個): 文件 「t.py」,第21行,在 S3_search1 = re.compile('(\ d \ d:\ d \ d:\ d \ d)。*?輸入文件=。*?(ABC | DEF)\\(。*?)\ soutput',re.IGNORECASE) 文件「c:\ python27 \ lib \ re.py「,第190行,編譯 return _compile(pattern,flags) 文件」c:\ python27 \ lib \ re.py「,第245行,在_compile中 引發錯誤,v#無效表達式 sre_constants。錯誤:括號不平衡 – user729544 2011-04-28 15:35:22

+0

@ user729544:對不起,在python中,您必須處理[The Backslash Plague](http://docs.python.org/howto/regex.html#the-backslash-plague)... one正則表達式可能不是一個好理由的更多理由在這種情況下的想法 – MarcoS 2011-04-28 15:55:47

+0

謝謝,它現在有效。是的,反斜線鼠疫是我錯過的。 – user729544 2011-04-28 16:14:05

0

這個工作對你的例子:

r'(\d\d:\d\d:\d\d).*(ABC|DEF).*?([^\\]*)\soutput.*' 

雖然寫得很好的正則表達式是適當這裏,我會採取不同的方式。最具體而言,os.path.split旨在將文件名與基本路徑分開,並處理此正則表達式忽略的所有邊界情況。

+0

謝謝,但如果文件名包含ABC或DEF,如20100722D1-ABC.TXT,則結果將僅爲.TXT,否則將失敗。 (\ d \ d:\ d \ d:\ d \ d)。*?輸入文件=。*?(ABC | DEF)\\\\(。*?)\ soutput可以正常工作。感謝MarcoS。 – user729544 2011-04-28 16:24:08

相關問題