2011-09-04 74 views
3

我不能用正則表達式,我正在尋找排除某些東西的語法。 我解析<,>,"&在html代碼(用&lt;等取代),我需要排除<br/>從解析。 即:Python中的正則表達式排除

<html><br/> 
    <head><title></title></head><br/> 
    <body><br/> 
    </body><br/> 
</html> 

我試着像sometihng即:r'<\b?![br]'等人,但他們並不完全工作。我用re.sub()來代替。

+0

我不能也不想安裝外部庫。 – stdio

+2

@stdio你不需要外部庫; Python附帶了開箱即用的ElementTree(lxml提供了更好的實現的API)。 –

+1

XML(像它擴展的SGML)不是一種常規語言(在計算機科學中這個術語的含義 - 如果你已經參加了編譯器設計課程,他們應該進入它)。正則表達式不足以解析它。 –

回答

2

好了,現在的問題是重新開放,我可以做到這一點作爲一個答案,所以......

除非我失去了一些東西,而一旦它只是<br/>(沒有任何變體),則可以只替換<(?!br/>)&lt;(?<!<br/)>&gt;這就是它?


在Python,它看起來像這意味着這樣的:

text = re.sub('<(?!br/>)' , '&lt;' , text) 
text = re.sub('(?<!<br/)>' , '&gt;' , text) 


爲了解釋這是怎麼回事,(?! ...... )是負前瞻 - 它只有在成功當一個位置相匹配以下文字不是與其包含的子表達式匹配。
(注向前看符號不消耗由他們的子表達式匹配的文本,他們只當它不存在,或者無法覈實。)

同樣,(?<! ... )是負的樣子背後和做同樣的事情,但使用前面的文字。

但是,lookbeheads與lookaheads(在一些正則表達式實現中)略有不同 - 也就是說,lookbehinds內部的子表達式必須表示固定寬度或有限寬度的匹配。

Python是需要固定寬度的那個 - 所以雖然上面的表達式工作(因爲它總是四個字符),如果它是(?<!<br\s*/?)>那麼它不會是Python的有效正則表達式,因爲它表示一個可變長度比賽。 (但是,可以將堆疊多個向後看,所以如果需要,您可以手動迭代各種選項。)

+0

我已經說過:完美;)現在,有沒有一種方法可以做到一步到位?對於正則表達式沒有問題,我可以使用'或'運算符(|),但有沒有辦法將re.sub()作爲第二個參數傳遞給多個值? – stdio

+1

你用不同的東西代替,所以你不能一步到位。那麼,我認爲PHP允許你傳遞一個數組(對於正則表達式和替換),但是這在Python文檔中沒有提及,所以如果它很重要的話,需要用戶定義的函數。當然,如果僅僅是一個不想臨時的情況,你也可以做're.sub('<(?!br/>)','<',re.sub('(?','>',text))'變量。 –

+0

簡單而好的解決方案。再次感謝 :) – stdio

0

替換一切,然後在第二遍替換「& lt; br/& gt;」與「< br/>」。

或者,爲了一般化,有一個你想'恢復'的標籤列表並替換爲「& lt; tag & gt;」與「<標記>」,「& lt;/tag & gt;」與「< /標記>」和「& lt; tag/& gt;」 「< tag/>」。

+1

更美好更優雅的東西?但是我更喜歡使用正則表達式。 – stdio

+0

@stdio:但這個答案*使用正則表達式。一旦你完成了所有的轉換,只需撤消你不想改變的標籤即可。 – tchrist

+0

@tchrist:是的,但它並不優雅,我更喜歡使用re.sub()在一個步驟中完成所有操作(不包括通過正則表達式的'br'標記解析)。 – stdio

0

這是否對應您需要的?:

import re 
import htmlentitydefs 

ss = ''' 
<html> 
    <br> 
     <title>"War & Peace"</title> 
     <body>Leon Tolstoy</body> 
    <br/> 
</html>''' 

print ss 
print '\n\n' 


uniquechars_repl = '"&' 
conditional_repl = {'<':'<(?!br/>)', 
        '>':'(?<!<br/)>'} 

all_repl = list(uniquechars_repl) + conditional_repl.keys() 

di = dict((b,'&%s;' % a) for a,b in htmlentitydefs.entitydefs.iteritems() 
      if b in all_repl) 

pat = '|'.join(list(uniquechars_repl) + conditional_repl.values()) 

text = re.sub(pat , lambda mat: di[mat.group()], ss) 

print text 

結果

<html> 
    <br> 
     <title>"War & Peace"</title> 
     <body>Leon Tolstoy</body> 
    <br/> 
</html> 




&lt;html&gt; 
    &lt;br&gt; 
     &lt;title&gt;&quot;War &amp; Peace&quot;&lt;/title&gt; 
     &lt;body&gt;Leon Tolstoy&lt;/body&gt; 
    <br/> 
&lt;/html&gt;