2013-05-18 44 views
1

我使用sub()函數將===Something here===替換爲<h2>Something here</h2>如何使用sub()在多行上匹配模式?

以下工作:

line = sub(r"(===)([a-zA-Z\s]*)(===)", r"<h2>\2</h2>", line) 

凡原內容爲:

===Something here=== 

但是它不工作時,原來的內容是:

=== 
Something here 
=== 

我曾嘗試諸如:

line = sub(r"(===\n)([a-zA-Z\s]*)(===)", r"<h2>\2</h2>", line) 

(唯一的變化是所述第一組中的另外的\n

但我認爲強制該圖案包含一個新行,而不是圖案的可選部分。

如何擴展當前模式,以便足夠靈活地識別新行可能存在的實例?

編輯:

我曾嘗試下面的建議(在寫作時),他們不工作。我能想到的唯一原因是因爲該行中可能還有其他字符。

以下圖像(「空白」設置爲顯示在賽特編輯器中打開帶有「生產線末端」和)正在讀取與原始文本文件的截圖:

original_text_file = open('file.txt', 'U') 

單線實例:

enter image description here

多行實例:

enter image description here

我不知道是否需要對這些角色進行其他考慮?

編輯二:從測試下面的另一溶液

結果(關於多實例此沒有執行替換):

Python代碼:

from re import * 

def test_function(text_file): 
    file_object = open(text_file+'.txt', 'U') 
    for line in file_object: 
     line = sub(r"\n?(===)\n?([a-zA-Z\s]*?)\n?(===)\n?\n?", r"<h2>\2</h2>", line) 
     print line 

test_function('my_file') 

my_file。TXT:

===Something here=== 

Lorem ipsum lala. 

=== 
Something here 
=== 

Loreum ipsum lala. 
+0

看到我更新的答案 – HennyH

回答

0

添加空格中捕獲組之間:

re.sub(r"(===)\s*([a-zA-Z\s]*?)\s*(===)", r"<h2>\2</h2>", line) 

您也可以使用非貪婪捕獲組:

re.sub(r"(===)\s*(.*?)\s*(===)", r"<h2>\2</h2>", line) 
+0

我試着在組之間添加'\ s *',並且它導致它不在工作的功能(沒有錯誤,它只是沒有輸出指定的信息)。第二個建議引起了同樣的行爲。我已經更新了上面的帖子,提供了更多信息。 – user1063287

1

我覺得用的這裏正則表達式是適當的。你的表情接近你所需要的。在\n之後,您需要?,它匹配01之前出現的字符,在此情況下爲0或1 \n。這必須放在幾個地方,以應付可能的換行。您還必須使目標捕獲組中的\s不消耗可選的\n,否則最終會在輸出中產生\n

import re 
pat = r'\n?(===)\n?([a-zA-Z\s]*?)\n?(===)\n?\n?' 
rep = r'<h2>\2</h2>' 

print(repr(re.sub(pat,rep,""" 
=== Something here === 
"""))) 
print(repr(re.sub(pat,rep,"""=== 
Something here 
==="""))) 

輸出

>>> 
'<h2> Something here </h2>' 
'<h2>Something here</h2>' 

我複製和粘貼文本從賽特建立了像你這樣的:

enter image description here


對於multline我會推薦這:

import re 
patSearch = r'\n?===\n?[a-zA-Z\s]*?\n?===' 
patReplace = r'\n?(===)\n?([a-zA-Z\s]*?)\n?(===)\n?\n?' 
replacement = r'<h2>\2</h2>' 

用繩子t

t="""===Something here=== 

Lorem ipsum lala. 

=== 
Something here 
=== 

Loreum ipsum lala.""" 

以下

matches = re.findall(patSearch,t) #get all the === ... === style string 
for match in matches: 
    print re.sub(patReplace,replacement,match) #do replacement in each one 

會產生

>>> 
<h2>Something here</h2> 
<h2>Something here</h2> 
+0

我在我正在使用的上下文中嘗試了這個建議,並且它沒有在多行實例上執行替換。我修改了上面的帖子,以顯示我的嘗試。 – user1063287

+0

@ user1063287好吧,我已更新它以反映文件的多行本質 – HennyH

1

我建議這個解決方案:

import re 
s = """===Something here=== 

Lorem ipsum lala. 

=== 
Something here 
=== 

Loreum ipsum lala. """ 
result = re.sub(r"===(.*?)===", r"<h2>\1</h2>", s, flags=re.DOTALL) 
print result 

幾點說明:

  • .*?在「非貪婪」模式的任何字符匹配:儘可能少的數據相匹配越好。這是爲了避免===First=== lalala ===Second===<h2>First=== lalala ===Second</h2>

  • flags=re.DOTALL取代意味着.比賽任何字符,包括您需要申請子()將整個文件,沒有行換行

注按行

1

編譯使用標誌的正則表達式re.DOTALL:這將使字符.也匹配換行符。應該使用$來強制結束模式。您再也不需要在Blender的解決方案中使用\s

0

User1063287,如果您仍有問題,我推薦Zac發佈的解決方案。我遇到了類似的問題,'re.DOTALL'標誌是允許我按照我的意圖進行替換的技巧。我的問題還涉及從.txt文件訪問文本。下面是如何編寫你的具體問題的基礎上,對我工作(注意,我輸出保存到一個新的.txt)

import re 
with open('output.txt', "w") as o: 
    with open('input', 'r') as i: 
     line = i.read() 
     line = re.sub(r"===.*?===", r"<h2>\2</h2>", line, flags=re.DOTALL)  
    o.write(line) 

的with語句可以讓你的輸入和輸出文件時關閉的建議循環完成,並且i.read()命令允許一次讀取整個文件(而不是逐行讀取)。我不明白爲什麼你不能把這個代碼放到def函數中,但我沒有試過。

祝你好運!