2009-12-09 194 views
12

使用str.format()是在Python 2.6和Python 3中格式化字符串的新標準。在正則表達式中使用str.format()時遇到了一個問題。Python 2.6+ str.format()和正則表達式

我寫了一個正則表達式返回是指定域下面一個級別的所有域名,或者是2級域名下面的規定,如果低於2級的WWW任何域...

假設指定的域是delivery.com,我的正則表達式應該返回a.delivery.com,b.delivery.com,www.c.delivery.com ...但它不應該返回xadelivery.com。

import re 

str1 = "www.pizza.delivery.com" 
str2 = "w.pizza.delivery.com" 
str3 = "pizza.delivery.com" 

if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str1): print 'String 1 matches!' 
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str2): print 'String 2 matches!' 
if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}delivery.com$', str3): print 'String 3 matches!' 

運行,這將給結果:

String 1 matches! 
String 3 matches! 

現在的問題是,當我嘗試使用動態str.format更換delivery.com ...

if (re.match('^(w{3}\.)?([0-9A-Za-z-]+\.){1}{domainName}$'.format(domainName = 'delivery.com'), str1): print 'String 1 matches!' 

這似乎失敗了,因爲str.format()預計{3}{1}是該函數的參數。 (我假設)

我可以使用+運算

'^(w{3}\.)?([0-9A-Za-z-]+\.){1}' + domainName + '$' 

的問題歸結爲字符串連接在一起,是有可能使用str.format()當字符串(通常是正則表達式)具有「{N}「內嗎?

+0

與這個問題沒有直接關係,但是通過養成在正則表達式中始終使用原始字符串的習慣,您將爲自己節省很多的痛苦。 – 2009-12-09 18:21:29

+0

@標記這是什麼原因?謝謝你的提示。 – brildum 2009-12-09 18:23:56

+4

通常,只要你在字符串文字中加入反斜槓,你應該使用原始字符串。否則,你可能會以意外的字符串轉義結束。這在Windows文件路徑中非常明顯,其中(非原始)「c:\ names \ bob」並不意味着您的想法。在正則表達式中,使用原始字符串表示您的正則表達式字符串是您輸入的內容。要匹配正則表達式中的單個反斜槓,您需要使用另一個反斜槓進行轉義:\\然而,非原始字符串中的這個序列會產生一個反斜槓,但從查看您的正則表達式並不明顯。在原始字符串中,您的r'\'會按預期方式通過。 – 2009-12-09 19:00:45

回答

20

你首先需要格式化字符串,然後使用正則表達式。把所有東西放在一條線上是不值得的。轉義是由大括號加倍做:

>>> pat= '^(w{{3}}\.)?([0-9A-Za-z-]+\.){{1}}{domainName}$'.format(domainName = 'delivery.com') 
>>> pat 
'^(w{3}\\.)?([0-9A-Za-z-]+\\.){1}delivery.com$' 
>>> re.match(pat, str1) 

此外,re.match是在字符串的開頭匹配,你不必把^如果使用re.match,你,如果你正在使用re.search需要^但是。

請注意,在正則表達式中{1}是相當多餘的。

+4

不僅'{1}'多餘,而且'www'不會比'w {{3}}更清晰。我知道它不回答原來的一般問題,但似乎是這種情況下更好的解決方案。 – 2009-12-09 20:30:42

7

the documentation,如果你需要一個文字{}生存的格式opertation,在原字符串中使用{{}}

'^(w{{3}}\.)?([0-9A-Za-z-]+\.){{1}}{domainName}$'.format(domainName = 'delivery.com')