2013-02-19 37 views
4

我有一個龐大的文件,我需要爲特定條目提供數據。文件結構是:提取兩個符號之間的多行數據 - 正則表達式和Python3

>Entry1.1 
#size=1688 
704 1 1 1 4 
979 2 2 2 0 
1220 1 1 1 4 
1309 1 1 1 4 
1316 1 1 1 4 
1372 1 1 1 4 
1374 1 1 1 4 
1576 1 1 1 4 
>Entry2.1 
#size=6251 
6110 3 1.5 0 2 
6129 2 2 2 2 
6136 1 1 1 4 
6142 3 3 3 2 
6143 4 4 4 1 
6150 1 1 1 4 
6152 1 1 1 4 
>Entry3.2 
#size=1777 
AND SO ON----------- 

我必須達到的是我需要提取某些條目的所有行(完整記錄)。對於e.x.我需要Entry1.1的記錄,而不是使用條目名稱> Entry1.1'直到下一個>>'作爲REGEX中的標記來提取它們之間的行。但我不知道如何構建這樣複雜的REGEX表達式。一旦我有這樣的表情我就會把它FOR循環:

For entry in entrylist: 
    GET record from big_file 
    DO some processing 
    WRITE in result file 

什麼可以進行記錄的這種提取特定條目正則表達式?有沒有更多的pythonic方式來實現這一目標?我很感謝你對此的幫助。

AK

+0

啊謝謝。我沒有看到你看到我的答案。如果您需要改進,請詢問。例如,有趣的是,用戶可以輸入** 1 1 **而不是** 1.1 ** – eyquem 2013-02-19 20:33:21

回答

4

用正則表達式

說明的
import re 

ss = ''' 
>Entry1.1 
#size=1688 
704 1 1 1 4 
979 2 2 2 0 
1220 1 1 1 4 
1309 1 1 1 4 
1316 1 1 1 4 
1372 1 1 1 4 
1374 1 1 1 4 
1576 1 1 1 4 
>Entry2.1 
#size=6251 
6110 3 1.5 0 2 
6129 2 2 2 2 
6136 1 1 1 4 
6142 3 3 3 2 
6143 4 4 4 1 
6150 1 1 1 4 
6152 1 1 1 4 
>Entry3.2 
#size=1777 
AND SO ON----------- 
''' 

patbase = '(>Entry *%s(?![^\n]+?\d).+?)(?=>|(?:\s*\Z))' 


while True: 
    x = raw_input('What entry do you want ? : ') 
    found = re.findall(patbase % x, ss, re.DOTALL) 
    if found: 
     print 'found ==',found 
     for each_entry in found: 
      print '\n%s\n' % each_entry 
    else: 
     print '\n ** There is no such an entry **\n' 

'(>Entry *%s(?![^\n]+?\d).+?)(?=>|(?:\s*\Z))'

1)

%s接收項的參考:1.1,2,2.1等

2)

部分(?![^\n]+?\d)是做驗證。

(?![^\n]+?\d)是負先行斷言,說什麼是後%s一定不能[^\n]+?\d的一個數字\d

我寫[^\n]之前說的任何字符[^\n]+?表示「任何換行符以外的\n 」。
我不得不寫這個,而不是簡單的.+?,因爲我把國旗re.DOTALL和模式部分.+?將採取行動,直到條目結束。
不過,我只是想驗證輸入的參考(%s所的模式表示)後,不會有該行的結束前補充位數,由輸入錯誤

所有這一切是因爲如果有一個Entry2.1但沒有Entry2,並且用戶只輸入2,因爲他想要Entry2而沒有其他的,正則表達式會檢測Entry2.1的存在並且會產生它,儘管用戶實際上真的很喜歡Entry2。

3)

截至'(>Entry *%s(?![^\n]+?\d).+?)末,部分.+?將趕上入學的完整塊,因爲點代表任意字符,包括換行符\n
它是這個目的,我把國旗re.DOTALL爲了使下面的圖案部分.+?能夠通過新行,直到輸入的結束。

4)

我想匹配停在入境所需的結束,而不是下一個內部,使得由parenthesises在(>Entry *%s(?![^\n]+?\d).+?)定義的組會趕上正是我們想要
因此,我把在結束了積極查找ahaed斷言(?=>|(?:\s*\Z)),指出該角色之前將運行ungreedy .+?必須停止,以配合或者是>(下一個條目的開頭)或字符串\Z結束。
因爲它有可能是最後一項結束將不完全是整個字符串的結尾,我把\s*,意思是「可能的空格結束前後」。
所以\s*\Z的意思是「可以有空格前碰到的字符串的結尾」 空格被一個blank\f\n\r\t\v

+0

謝謝...像一個魅力工作.... – Bade 2013-02-19 20:17:21

+1

謝謝。請注意,我使用'found = re.findall(patbase%x,ss,re.DOTALL)',認爲可能會有幾個Entry具有相同的引用。如果不是的話,你應當以書面形式直接''打印簡化代碼 '\ n%S \ n' %re.search(patbase%×,SS,re.DOTALL)。集團()'' - 了' '打印'發現==',發現''是一個煤渣沒有需要 – eyquem 2013-02-19 20:44:01

0

不完全確定你在問什麼。這會讓你更接近嗎?它將把你的所有條目作爲字典鍵和所有條目的列表。假設它的格式就像我相信的那樣。它是否有重複的條目?下面是我得到了什麼:

entries = {} 
key = '' 
for entry in open('entries.txt'): 
    if entry.startswith('>Entry'): 
     key = entry[1:].strip() # removes > and newline 
     entries[key] = [] 
    else: 
     entries[key].append(entry) 
+0

如果我不夠清楚,我很抱歉。實際上文件太大(〜1GB),所以我只想要一個字符串匹配而不是提取條目。 'eyquem'的回答很好地完成了這項工作。 – Bade 2013-02-19 20:19:37

+0

這很好。無需道歉:-)抱歉,我無法提供更多幫助。 – Hoopdady 2013-02-19 20:25:34

+1

@Atul如果該文件是非常大的,它可能是有問題的使用正則表達式,因爲它需要加載的文件的全部內容到內存中。通過使用正則表達式塊瀏覽文件需要一些棘手的過程,因爲如果塊本身不重疊,用正則表達式搜索的文本的期望部分可以重疊在兩個塊上。我清楚了嗎? – eyquem 2013-02-19 20:48:13

1

我不好用正則表達式,所以我儘量儘可能尋找非正則表達式解決方案。在Python中,存儲迭代邏輯的天然場所是發電機,所以我會用這樣的(無itertools要求的版本):

def group_by_marker(seq, marker): 
    group = [] 
    # advance past negatives at start 
    for line in seq: 
     if marker(line): 
      group = [line] 
      break 
    for line in seq: 
     # found a new group start; yield what we've got 
     # and start over 
     if marker(line) and group: 
      yield group 
      group = [] 
     group.append(line) 
    # might have extra bits left.. 
    if group: 
     yield group 

在您的例子情況下,我們得到:

>>> with open("entry0.dat") as fp: 
...  marker = lambda line: line.startswith(">Entry") 
...  for group in group_by_marker(fp, marker): 
...   print(repr(group[0]), len(group)) 
...   
'>Entry1.1\n' 10 
'>Entry2.1\n' 9 
'>Entry3.2\n' 4 

這種方法的一個優點是我們永遠不必在內存中保留多個組,所以它對於真正的大文件很方便。它並不像正則表達式那樣快,但如果文件是1 GB,那麼無論如何你都可能會受到I/O限制。

+0

非常好,謝謝! ~~我想知道,我們如何才能在Python 3上完成這項工作?編輯:nevermind,不知何故,我確實在Python 2上得到了輸出,但在3上沒有輸出,但畢竟它在Python 3上工作。 – arjan 2016-03-16 14:39:15

相關問題