2012-10-04 89 views
-3

我有一個包含形式搜索,替換和使用正則表達式

XXX 
Some random text. Let's call it text A 
    and it might span 
several lines. 
Some more random text. Let's call it 
text B. It might also span several lines. 
And finally some 
    text that we call C. 
YYY 

許多塊,每個塊有固定字符串XXX開始,以YYY結束,總是一個文本文件中的文本文件交換字符串。在XXX和YYY之間,有一些文本行總是可以被識別爲文本A,B和C,如下所示。

  • 文本是XXX後第一串和運行,直到有一個完整 停止/句號(。),緊接着一個新行。
  • 然後文本B開始,這也 運行,直到有一個完全停止/句點(。)緊接着一個新行。
  • 然後有一個文本C運行到YYY。

我想拔出文字A,B,C每個XXX,YYY塊,每次一個塊,做一些簡單的改變給他們,叫新文本A「 B」和C」,並將它們放回到塊中,但A'和B'互換。也就是說,新的塊應該讀

XXX 
text B' 
text A' 
text C' 
YYY 

一切都非常乾淨; XXX和YYY僅用作塊的分隔符,這三個文本總是存在於一個塊中,並且定義良好。在塊之間可能有隨機文本。

我需要用Python解決這個任務。任何人都可能指出我找到解決這個問題的正確方向?我知道重新模塊會很有用,但是考慮到細節的數量,它很可能需要一些小小的欺騙。有沒有好的例子可以在線閱讀這個特定的任務,而無需學習關於Python和正則表達式的所有細節?

+5

問題是什麼? – Krab

+0

Python中有一個're'包用於處理正則表達式。 – Krab

+2

它聽起來像你已經定義你的任務非常好,你也選擇了這個任務的正確工具:正則表達式。很好。現在看來是什麼問題? – zenpoy

回答

1

用下面的代碼就可以實現你的目標(我目前還沒有測試它,所以請原諒一些問題:))

UPDATE

修改後的代碼實現了從評論的要求

import re 
pat = re.compile(r"XXX\s(.*?\.[\r\n]+)(.*?\.[\r\n]+)(.*?\.[\r\n]+)\s?YYY", re.S) 
with open("myTextFile.txt") as in: 
    content = in.read() 
    text_before_firstXXX = re.search(r"^(.*?)XXX", content, re.S).group(1) 
    text_after_lastYYY = re.search(r".*YYY(.*)", content, re.S).group(1) 
    text_between_YYY_and_XXX = re.findall(r"YYY(.*?)XXX", content, re.S) 
    all_blocks = pat.findall(content) 
    result=[] 
    for block in all_blocks: 
     A, B, C = block[0], block[1], block[2] 
     A = make_changes_to_block(A) 
     B = make_changes_to_block(B) 
     C = make_changes_to_block(C) 
     result.append(("XXX\n", B, A, C, "YYY\n")) 
    with open("newTextFile.txt", "w") as out: 
     out.write(text_before_firstXXX) 
     length_text_between = len(text_between_YYY_and_XXX) 
     for i, block in enumerate(result): 
      out.write("".join(block)) 
      if i < length_text_between: 
       out.write(text_between_YYY_and_XXX[i]) 
     out.write(text_after_lastYYY) 

如果您有任何問題,請不要猶豫,問問他們。

+0

謝謝!你的例子是非常豐富和有益的。有一點它沒有捕獲的細節:在輸出文件中,我希望將文本保留在每個YYY和XXX對之間,而不是丟棄它。我想可以引入第四個參數D.但是,爲了使它更加複雜,我還需要保留在第一個XXX之前和最後一個YYY之前的文本。所有這些邊界情況... :) – Jalamaar

+0

@Jalamaar我編輯了代碼。這應該包括你的邊界情況:) – halex

+0

非常有幫助,謝謝。我從中學到了很多東西。 – Jalamaar

1

這部分取決於您正在運行的系統和文件大小。對大文件進行運行(即將整個文件視爲字符串)非常麻煩,並且隨着文件大小的增加,性能會受到很大影響。

對於初學者來說,如果你需要避免再次你可以:

data = open('fileName.txt','r').read().split('.') 
A = data[0:-1:3] 
B = data[1:-1:3] 
C = data[2:-1:3] 

# Perform replacements. 
A' = [re.sub(replacement param) for r in A] 
B' = [re.sub(replacement param) for r in B] 
C' = [re.sub(replacement param) for r in C] 

# Rebuild 
result = [] 
result.append(('XXX\n, B, A, C, 'YYYY\n')) 

你必須與你的特定需求完成這一關,但這是重新使用的替代品。老實說,如果你的字符串不是太長(而且他們可能不是),那麼就像halex所示的那樣提供一個優雅的解決方案。

+0

是的,你是對的。爲了我的目的,我可以在全文中閱讀,所以halex的簡潔解決方案確實很好。 – Jalamaar

0

試試這個:

def getBlocks(filepath): 
    answer = [] 
    with open(filepath) as f: 
     for line in f: 
      if line.strip() == "XXX": 
       block = [] 
      elif line.strip() == "YYY": 
       answer.append(''.join(block)) 
      else: 
       block.append(line) 
    return answer 

def normalizeBlocks(blocks): 
    answer = [] 
    for block in blocks: 
     A, B, C = block.split('.\n') 
     A = changesToA(A) 
     B = changesToB(B) 
     C = changesToC© 
     answer.append([A, B, C]) 
    return answer 

def writeOut(blocks, fpath): 
    with open(path, 'w') as f: 
     for A, B, C in blocks: 
      f.write("XXX\n" + '\n'.join([B, A, C]) + "YYY\n") 

def main(infilepath, outfilepath): 
    blocks = normalizeBlocks(getBlocks(infilepath)) 
    writeOut(blocks, outfilepath) 

希望這有助於

+0

謝謝,這很有趣,因爲它不使用正則表達式,可能有人可能會爭論這個任務是過度的。我很感謝你的回答。 – Jalamaar