2016-08-23 53 views
0

我試圖刪除字符\/<>~?`%,如果它們出現在三個&lt;&gt;之內。正則表達式匹配中的部分替換/刪除字符

對於字符串:

<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;test/verify&gt;&gt;&gt; in &lt;&lt;&lt;one% g?o&gt;&gt;&gt;</body></html>

(讀起來就像Multiple <<<parameter>>> options %to <<<test/verify>>> in <<<one% g?o>>>)。

最後一個字符串我想要的是:

<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;testverify&gt;&gt;&gt; in &lt;&lt;&lt;one go&gt;&gt;&gt;</body></html>

注意的是,在 '%' '%to'不會被刪除,因爲它不在三個&lt;和之間的。

我想這些正則表達式的迄今:

>>> s = '<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;test/verify&gt;&gt;&gt; in &lt;&lt;&lt;one% g?o&gt;&gt;&gt;</body></html>' 
>>> 
>>> # just getting everything between <<<and>>> is easy 
... re.sub(r'((?:&lt;){3})(.*?)((?:&gt;){3})', r'\1\2\3', s) 
'<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;test/verify&gt;&gt;&gt; in &lt;&lt;&lt;one%? go&gt;&gt;&gt;</body></html>' 
>>> re.findall(r'((?:&lt;){3})(.*?)((?:&gt;){3})', s) 
[('&lt;&lt;&lt;', 'parameter', '&gt;&gt;&gt;'), 
('&lt;&lt;&lt;', 'test/verify', '&gt;&gt;&gt;'), 
('&lt;&lt;&lt;', 'one%? go', '&gt;&gt;&gt;')] 

但試圖讓非\/<>~?`%字符doesn't work序列因爲任何包含它只是被排除:

>>> re.findall(r'((?:&lt;){3})([^\\/<>~?`%]*?)((?:&gt;){3})', s) 
[('&lt;&lt;&lt;', 'parameter', '&gt;&gt;&gt;')] 
>>> re.findall(r'((?:&lt;){3})((?:[^\\/<>~?`%]*?)*?)((?:&gt;){3})', s) 
[('&lt;&lt;&lt;', 'parameter', '&gt;&gt;&gt;')] 
>>> re.findall(r'((?:&lt;){3})((?:[^\\/<>~?`%])*?)((?:&gt;){3})', s) 
[('&lt;&lt;&lt;', 'parameter', '&gt;&gt;&gt;')] 

回答

2

我去解決方案正在使用原始<<<.*>>>正則表達式和repl as a function選項re.sub

>>> def illrepl(matchobj): 
...  return ''.join([matchobj.group(1), 
...      matchobj.group(2).translate(None, r'\/<>~?`%'), 
...      matchobj.group(3)]) 
... 
>>> re.sub(r'((?:&lt;){3})(.*?)((?:&gt;){3})', illrepl, s) 
'<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;testverify&gt;&gt;&gt; in &lt;&lt;&lt;one go&gt;&gt;&gt;</body></html>' 
>>> # verify that this is the final string I wanted: 
... re.sub(r'((?:&lt;){3})(.*?)((?:&gt;){3})', illrepl, s) == '<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;testverify&gt;&gt;&gt; in &lt;&lt;&lt;one go&gt;&gt;&gt;</body></html>' 
True 

而且由於我不需要更改&lt;&gt;,我知道匹配僅適用於其中的內容,所以我可以爲正則表達式的這些部分使用非捕獲組或者簡化該illrepl功能有點只要使用全場比賽對象爲group(0)刪除非法/無效字符:

>>> def illrepl(matchobj): 
...  # return matchobj.group(0).translate(None, r'\/<>~?`%') # may have unicode so can't use this 
...  return re.sub(r'[\/<>~?`%]*', '', matchobj.group(0)) 
... 
>>> re.sub(r'(?:&lt;){3}(.*?)(?:&gt;){3}', illrepl, s) 
'<html><body>Multiple &lt;&lt;&lt;parameter&gt;&gt;&gt; options %to &lt;&lt;&lt;testverify&gt;&gt;&gt; in &lt;&lt;&lt;one go&gt;&gt;&gt;</body></html>' 

,如果有一種方法,我只能通過正則表達式,而不需要使用已經做到了這一點不能肯定illrepl函數來生成替換,並且不得不在其內部使用re.sub

+1

你確實需要一個回調才能做到這一點。這是正確的選擇。 – sln

+0

@sln好的,謝謝。將接受我的解決方案作爲答案。 – aneroid

相關問題