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


這里是一點小心得:由於下面兩個原因,在正則表達式中使用反斜杠就會產生了一個雙重轉換的問題。
(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。
 
參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM