2017-02-05 32 views
0

我需要從不同的文本文件中提取(很多)信息。 不知有比以下內容的更短和更有效的方式:使用re.compiler提取數據的最佳方式

第一部分:(N線長)

N1 = re.compile(r'') 
N2 = re.compile(r'') 
. 
Nn = re.compile(r'') 

第二部分:(2N線長)

with open(filename) as f: 
    for line in f: 
    if N1.match(line): 
     var1 = N1.match(line).group(x).strip() 
    elif N2.match(line): 
     var2 = N1.match(line).group(x).strip() 
    elif Nn.match(line): 
     varn = Nn 

你是否建議讓re.compile變量(第一部分)與第二部分分開?你們在這種情況下使用什麼?也許一個函數將正則表達式作爲參數?並每次調用它。

在我的情況下,N是30,這意味着我有90行用於填充字典的行數很少或根本沒有邏輯。

+1

一般來說,如果你想'''的東西,使用*列表*。 – jonrsharpe

+0

提取的數據將存儲在列表和字典中,但爲什麼在提取之前使用列表? –

+0

...因爲您希望比定義具有不同名稱的'n'編譯正則表達式更短,更高效? – jonrsharpe

回答

0

我要試圖回答這個沒有真正知道你是什麼實際上做什麼。所以這個答案可能對你有幫助,或者它可能不會。

首先,re.compile所做的是預編譯一個正則表達式,因此您可以稍後使用它,而不必在每次使用它時編譯它。當你有一個在你的程序中多次使用的正則表達式時,這是非常有用的。但是如果表達式只用了幾次,那麼事先編譯它並沒有什麼好處。

所以你應該問問自己,代碼運行的頻率如何,試圖匹配所有這些表達式。腳本執行期間是否只有一次?然後,可以通過內聯表達式來簡化代碼。由於您正在爲文件中的每一行運行匹配項,因此預編譯可能在此處有意義。

但是,只是因爲你預編譯了表達式,這並不意味着你應該馬虎,並且經常匹配相同的表達式。看看這個代碼:

if N1.match(line): 
    var1 = N1.match(line).group(x).strip() 

假設有一個匹配,這將運行兩次N1.match()。這是一個應該避免的開銷,因爲匹配表達式可能相對昂貴(取決於表達式),即使表達式已經預編譯。

相反,只匹配了一次,然後再用結果:

n1_match = N1.match(line) 
if n1_match: 
    var1 = n1_match.group(x).strip() 

看你的代碼,你的正則表達式也顯得mutally異或至少你永遠只用第一場比賽,並跳過其餘的。在這種情況下,您應該確保您訂購支票 ,以便最常用的支票首先完成。這樣,你避免運行太多無論如何都不匹配的表達式。另外,嘗試對它們進行排序,以減少更復雜的表達式的運行次數。

最後,您正在收集單獨變量varN的匹配結果。在這一點上,我在質疑你到底在做什麼,因爲在你所有的檢查之後,你沒有一個明確的方法來弄清楚結果是什麼以及使用哪個變量。在這一點上,將它收集到單個變量中或者在條件體內移動特定的邏輯可能更有意義。但很難分辨您提供的信息量。

+0

大多數預編譯的RE將被用於每個文件一次(或兩次),但腳本將每天運行一百個文件。 是的。他們是相互排斥的,如果他們匹配一條線我100%肯定該線不會有任何其他信息。我知道文件結構,所以如果我知道最後一行總是有我需要的數據,那麼我就把這個re.match放到最後。 在for的結尾處,每個var將輸入3個字符。出於這個原因,我在那裏有那些變數。主要的字典將會或多或少地受到110個文件的影響。 我真的不知道這是從更多還是更少結構化文本/日誌文件中獲取數據的最佳方式 –

+0

如果腳本運行多次,但運行它的Python進程在兩者之間終止,則預編譯表達式將無濟於事。 – poke

0

正如在re module documentation中提到的那樣,通過re方法傳遞的正則表達式被緩存:根據表達式的數量,自己緩存它們可能沒有用處。

這就是說,你應該列出你的正則表達式,這樣一個簡單的for循環可以讓你測試所有的模式。

regexes = map(re.compile, ['', '', '', '', ...]) 
vars = ['']*len(regexes) 
with open(filename) as f: 
    for line in f: 
    for i,regex in enumerate(regexes): 
     if regex.match(line): 
     var[i] = regex.match(line).group(x).strip() 
     break # break here if you only want the first match for any given line. 
+0

請注意,OP的代碼在第一次匹配時停止,而您的循環將始終匹配所有表達式。 – poke

+0

@poke你說得對,我已經更新了我的例子。 – Faibbus