1. 程式人生 > >python 正則表達式中反斜杠()的麻煩和陷阱 (轉)

python 正則表達式中反斜杠()的麻煩和陷阱 (轉)

[] 內部 ica con re模塊 .com 斜杠 字符 pat

這裏是一點小心得:由於下面兩個原因,在正則表達式中使用反斜杠就會產生了一個雙重轉換的問題。
(1)、python自身處理字符串時,反斜杠是用於轉義字符

(2)、正則表達式也使用反斜杠來轉義字符

要匹配字符串中1個反斜杠應該怎麽寫正則表達式?"\\",這樣行嗎?試試就知道了,re模塊拋異常了,因為在正則表達式中,"\\"就是一個反斜杠,對於正則表達式解析器來說,是一個轉義字符,但是後面啥也沒有,自然就報錯了,"\\\"三個肯定是不行的,試試四個"\\\\",完美匹配。
代碼如下:
import re
re_str_patt = "\\\\"
reObj = re.compile(re_str_patt)
str_test = "abc\\cd\\hh"
print reObj.findall(str_test)

輸出[‘\\‘, ‘\\‘] 備註: 1、第二行代碼只使用了python非原生字符串,所以它在正則表達式中表示的是一個反斜杠。(即四合一) 2、由於python字符串中,反斜杠表示轉義,所以第四行代碼中的字符串表示的是: abc後是一個反斜杠,然後接cd,再接一個反斜杠,然後是hh 3、代碼段輸出的是一個列表,列表中有兩個元素。每一個元素都是一個字符串(python中的字符串), 所以列表的第一個元素實際是表示一個反斜杠,同樣,列表的第二個元素也是表示一個反斜杠。 4、輸出也可能是這樣的:[r‘\‘, r‘\‘] 兩種輸種輸出效果是一致的。 代碼如下改動:
import re
re_str_patt = r"\\\\"
reObj = re.compile(re_str_patt)
str_test = "abc\\cd\\hh"
print reObj.findall(str_test)


輸出:[] 備註: 1、第二行代碼改成了原生字符串,此時正則表達式要匹配的則是兩個連續的反斜杠。(即二合一) 2、第四行代碼中的字符串表示的是:abc後是一個反斜杠,然後接cd,再接一個反斜杠,然後是hh。 3、所以沒有匹配的內容,輸出為一個空列表。
對於第一段代碼要這麽理解,首先第一重轉換是字符串自身的轉義,那麽"\\\\",實際上就是表示兩個反斜杠(兩個字符),然後傳入正則表達式
解析器,因為反斜杠依然是轉義字符,那麽進行第二重轉換,兩個反斜杠就代表一個反斜杠,所以就能和一個反斜杠進行匹配了,那麽匹配連續的兩個反斜杠,寫正則表達式時就要寫8次"\"了,相當壯觀。\d+在正則表達式裏面表示匹配連續1一個以上的數字字符,可是如果想匹配:一個反斜杠,後接字母d,再接一個加號 ,這個字符串怎麽寫呢?(答案:"\\\\d\\+") 代碼如下:
import re
re_str_patt = "\\\\d\\+"
print re_str_patt
reObj = re.compile(re_str_patt)
print reObj.findall("\\d+")
輸出:\\d\+
[‘\\d+‘]

寫成re_str_patt = "\\\\d\+"也行,因為\+對於字符串來說,沒有轉義意義,所以就當成一個反斜杠了。
在python中寫正則表達式時用得最多的是raw字符串,原生字符串,什麽意思?就是只有一重轉換了,沒有字符串轉換了,只在正則表達式內部進行轉換了,這樣匹配一個反斜杠的正則表達式可以這樣寫,re_str_patt = r"\\"。 有人會想,以後寫windows的文件路徑什麽的方便了,呵呵直接 path = r"c:\myforder\xx" 搞定,是的,這句沒有問題,但是如果你寫成 path = r"c:\myforder\xx\",直接報錯了,為什麽?因為反斜杠雖然不作為轉義字符了,但是還是對它後面的引號(包括單引號)有影響,使這個引號不被視為字符串的終止,以為它後面還有字符,但是實際沒有,因此會報錯。 其實可以反過來想raw字符串裏面要表示引號怎麽辦呢?,可以發現 path = r"\\123\"xxx" 是可以的,那用raw字符串豈不是有局限性?不過raw在設計之初就是用來支持正則表達式的,而在正則裏面反斜杠是轉義字符,所以不可能出現在字符串的末尾的,所以建議不要圖方便在其他的地方使用raw。

python 正則表達式中反斜杠(\)的麻煩和陷阱 (轉)