不管哪一種語言,在使用正則表達式的時候都避免不了一個問題,就是在匹配元字符的時候,須要對元字符進行轉義,讓python
正則表達式引擎將其當作普通字符來匹配。本文主要以python爲例,說明一下轉義中須要注意的問題。正則表達式
python的正則表達式中須要轉義的元字符有如下幾個:spa
python中對元字符的轉義使用雙反斜槓 \\ 來表示code
# 普通元字符的轉義 _string = ''' !@#$%^& ''' # 不轉義 print re.findall('$', _string) #>>> ['', ''] # 雙反斜槓轉義 print re.findall('\\$', _string) #>>> ['$'] # 單反斜槓轉義 print re.findall('\$', _string) #>>> ['$']
看上面的例子你們可能會發現,使用一個反斜槓 \ 也能夠達到轉義的效果,那爲何還要寫兩個呢?這得先搞清楚pythonblog
的字符串轉義(不是正則表達式轉義),python自己使用 \ 來轉義一些特殊字符,好比在字符串中加入引號的時候,爲了字符串
s = 'i\'m superman' print s #>>> i'm superman
防止和字符串自己的引號衝突,使用 \ 來轉義,通常狀況下這個也不會引發什麼問題,可是當你要使用 \ 來轉義 \ 的時候,get
就比較混亂了,好比咱們想要輸出一個 \ ,得寫兩個 \ ,不然會報語法錯誤,由於 \ 把後面的引號給轉義了,必須使用 \ string
# 錯誤寫法 # print '\' # 正確寫法 print '\\' #>>> \ # 原生字符串 print r'\\' #>>> \\
將 \ 轉義一下使其不具有轉義功能,才能夠正確輸出,當使用原生字符串的時候,輸出顯示了兩個 \ ,看起來好像是寫幾個class
輸出幾個的樣子,若是這樣想的話,你能夠試一下,看能不能輸出奇數個 \。語法
先來講一下什麼是原生字符串,其實就是不進行特殊處理的字符串,所謂特殊處理,貌似就是針對轉義的,原生字符串
的誕生自己就是爲了解決轉義的時候寫了太多 \ 的問題,可是爲何使用了原生字符串仍然不能只輸出一個 \ 呢?其實這應
該算是一個bug,就是python的字符串不能以奇數個 \ 結尾,這樣的寫法會被認爲是將結尾的引號進行了轉義,致使語法錯
誤。具體能夠參考http://t.cn/RfolM3H。
雖然原生字符串並非很完美,但它已經能夠幫咱們解決很大一部分問題了。好比當你想匹配 \ 的時候,原生字符串可
_string = '\\\\' print _string #>>> \\ # 字符串 for i in re.findall('\\\\', _string): print i #>>> \ #>>> \ # 原生字符串 for i in re.findall(r'\\', _string): print i #>>> \ #>>> \
以讓你少寫一半的 \ ,既節省代碼量,又增長可讀性。
說了這麼多也沒說爲何在寫正則表達式的時候一個 \ 也能夠起到轉義的做用。咱們先來分析一下一個字符串被正則表
達式引擎解析的過程,一共有4步:
# 字符串 # '\\\\' # 通過python處理以後 # '\\' # 正則表達式引擎接收到的 # '\\' # 正則表達式引擎進行轉義處理後 能夠匹配到 \ # '\'
而當使用原生字符串的時候就變爲了3步
# 原生 # '\\' # 再也不處理 # '\\' # 正則表達式引擎接收到的 # '\\' # 正則表達式引擎進行轉義處理 # '\'
下面是最重要的一個,當使用一個 \ 轉義的時候,python會識別不了轉義序列,因而它就不作任何處理,直接傳給了
正則表達式引擎。這就解釋了爲何一個 \也能夠轉義。這個不算bug,雖然方便了使用,但會讓人很迷惑,有利有弊吧。
# 原生 # '\$' # 識別不了 不進行處理 # '\$' # 正則表達式引擎接收到的 # '\$' # 正則表達式引擎進行轉義處理 # '$'
下面舉幾個例子看一下
# 匹配 \d+ _string = 'i am \d+' print re.findall('\\\\d\\+', _string)[0] #>>> \d+ print re.findall(r'\\d\+', _string)[0] #>>> \d+ # 匹配 [] _string = 'i am []' print re.findall('\\[\\]', _string)[0] #>>> [] print re.findall('\[\]', _string)[0] #>>> [] print re.findall(r'\[\]', _string)[0] #>>> []