2009-05-20 31 views
4

長話短說,我有兩個正則表達式模式。一個模式匹配我想要替換的事物,另一個模式匹配那些不應該被替換的模式的特例。舉個簡單的例子,假設第一個是「\ {。* \}」,第二個是「\ {\ {。* \} \}」。然後應該替換「{this}」,但「{{this}}」不應該。有沒有簡單的方法來取一個字符串,並說「只要第一個字符串的所有實例都替換爲」hello「,只要它不匹配第二個字符串」?僅當它與另一個正則表達式(Python)不匹配時才替換正則表達式

換句話說,有沒有辦法讓一個正則表達式「匹配第一個字符串,而不是第二個」很容易不修改第一個字符串?我知道我可以手動修改我的第一個正則表達式,從不匹配第二個正則表達式的實例,但是隨着第一個正則表達式變得更加複雜,變得非常困難。

回答

4

你可以給替換函數(reference

但要確保第一個正則表達式包含第二個。這只是一個例子:

regex1 = re.compile('\{.*\}') 
regex2 = re.compile('\{\{.*\}\}') 

def replace(match): 
    match = match.group(0) 
    if regex2.match(match): 
     return match 
    return 'replacement' 


regex1.sub(replace, data) 
1

您可以用替換字符串(將包括{{}}個字符串替換所有{}實例,然後用對其自身的後向引用替換{{}}(將第一個替換替換爲原始數據) - 那麼只有{}實例會發生變化。

+0

你能給我一個如何在Python中做到這一點的例子嗎?我不太清楚我的理解。謝謝! – So8res 2009-05-20 16:56:55

+0

我可以在大約一個小時內,但不是現在,對不起... – 2009-05-20 16:58:45

0

這在我看來是次優來匹配兩個不同的正則表達式,當你在尋找什麼是真正的一個模式。爲了說明:

import re 
foo = "{{this}}" 
bar = "{that}" 
re.match("\{[^\{].*[^\}]\}", foo) # gives you nothing 
re.match("\{[^\{].*[^\}]\}", bar) # gives you a match object 

所以這真的是你的正則表達式,可能會更精確一點。

6

使用負前瞻/後面斷言

pattern = re.compile("(?<!\{)\{(?!\{).*?(?<!\})\}(?!\})") 
pattern.sub("hello", input_string) 

負前瞻/後面斷言允許您比較多的字符串,但不被視爲使用了字符串的一部分的比賽。在斷言之前還有一個正常的查看,只有當字符串IS在給定模式後面/之前時,纔會使字符串匹配。

這是混淆找了一下,在這裏它是在片:

"(?<!\{)" #Not preceded by a { 
"\{"  #A { 
"(?!\{)" #Not followed by a { 
".*?"  #Any character(s) (non-greedy) 
"(?<!\})" #Not preceded by a } (in reference to the next character) 
"\}"  #A } 
"(?!\})" #Not followed by a } 

所以,我們正在尋找一個{周圍沒有任何其他{的,其次是一些字符,然後是}沒有任何其他的}圍繞它。

通過使用負前視/後置斷言,我們將其壓縮爲單個正則表達式,該表達式將成功匹配字符串中任何位置的單個{}。

另外,請注意*是一個貪婪的運算符。它將盡可能匹配。如果您使用"\{.*\}",並且文本中有多個{}塊,則它們之間的所有內容都將與其一起進行處理。

「這是一些示例文本{塊1}更多文本,看着我消失{塊2}甚至更多的文本」

成爲

「這是一些示例文本你好甚至更多而不是文字」

「這是一些示例文本你好更多文本,看着我消失你好甚至更多的文本」

要得到我們需要使其非貪婪通過附加一個適當的輸出?

python文檔在呈現re庫方面做得很好,但真正學習的唯一方法是進行實驗。