2015-04-15 32 views
6

İki dizge arasında oluşan metni çıkarmak için regex'i kullanmak istiyorum. Her seferinde aynı dizgiler arasında (ve örneğin Regex matching between two strings?'u soran sayısız soru) ayıklamak istediğimi biliyorum, ancak bunu değiştiren değişkenleri kullanarak yapmak istiyorum ve Regex içinde özel karakterler de içerebilirler. (Herhangi bir özel karakter istiyorum, örneğin * metin olarak kabul edilir). Örneğinİki dizge arasında ayıklamak için regex (değişkenler)

i olsaydı:

text = "<b*>Test</b>" 
left_identifier = "<b*>" 
right_identifier = "</b> 

i Aşağıdaki kod olmanın vadede yol açacağı regex kodu oluşturmak isteyeyim:

re.findall('<b\*>(.*)<\/b>',text) 

Ben don <b\*>(.*)<\/b> parçasıdır' Dinamik olarak nasıl yaratılacağını bilir.

+3

geri düşmek tavsiye eder: (.? *) '' Bu mümkün olduğunca az karakterle eşleşir. "{left_identifier} öğe {right_identifier} {sol tanımlayıcı} daha fazla öğe {right_identifier}" gibi bir dize durumunda, "stuff {right_identifier" yerine iki ayrı maçta yalnızca "stuff" ve "daha fazla şeyler" bulacaksınız } {sol tanımlayıcı} daha fazla öğe "bir maçta. – Shashank

+0

Teşekkürler - iyi nokta - haklısın - açgözlü olmayan niceleyici demek istediğim buydu! – kyrenia

+1

Lütfen HTML'yi ayrıştırmak için regex kullanmanın [önerilmez] olduğunu unutmayın (http://stackoverflow.com/a/1732454/405017). Bir HTML ayrıştırıcısı kullanmalısınız (Python'un [Nokogiri] (http://nokogiri.org) eşdeğeri ne olursa olsun) ve sonra uygun etiketlerden metin ayıklamanız gerekir. – Phrogz

cevap

4

Sen tanımlayıcıları re.escape gerekir:

>>> regex = re.compile('{}(.*){}'.format(re.escape('<b*>'), re.escape('</b>'))) 
>>> regex.findall('<b*>Text</b>') 
['Text'] 
4

regex, sadece bir dize şekilde left_identifier + text + right_identifier onun hayatını başlar ve

re.compile yılında Ya da kullanın:

re.findall('{}(.*){}'.format(left_identifier, right_identifier), text) 

çok çalışır.

>>> text = "<b*>Test</b>" 
>>> left_identifier = "<b*>" 
>>> right_identifier = "</b>" 
>>> s='{}(.*?){}'.format(*map(re.escape, (left_identifier, right_identifier))) 
>>> s 
'\\<b\\*\\>(.*?)\\<\\/b\\>' 
>>> re.findall(s, text) 
['Test'] 
Yan not

, str.partition(var) alternatif geçerli:

Sen meta gibi yorumlanır istemiyorsanız onlar re.escape ile regex meta karakter içeriyorsa değişkenlerde dizeleri kaçmak gerekir yolu bunu yapmak için:

>>> text.partition(left_identifier)[2].partition(right_identifier)[0] 
'Test' 
5

Böyle bir şey yapabilirsiniz:

import re 
pattern_string = re.escape(left_identifier) + "(.*?)" + re.escape(right_identifier) 
pattern = re.compile(pattern_string) 

kaçış işlevi otomatik özel karakterler kaçacaktır. eg için:

>>> import re 
>>> print re.escape("<b*>") 
\<b\*\> 
+1

Ayrıca açgözlü yakalama olmayan '(. *)' Yerine '(. *?)' Dır. Hangisi burada istersen öyle. –

0

Ben aslında regex çözüm istediğini biliyorum, ama regex we all have taken oath not to dikkate burada doğru araçtır eğer gerçekten merak ediyorum. html dizeleri ayrıştırma, hep olmayan bir açgözlü niceleyici düşünebilir beautifulsoup

>>> import bs4 
>>> bs4.BeautifulSoup('<b*>Text</b>').text 
u'Text' 
İlgili konular