2015-11-07 64 views
8

我對正則表達式中的反斜槓感到困惑。在正則表達式中,\具有特殊含義,例如\d表示十進制數字。如果您在反斜槓前添加反斜槓,這個特殊含義就會丟失。在regex-howto可以閱讀:Python中的反斜槓正則表達式

也許最重要的元字符是反斜槓,\。正如在Python字符串文字中一樣,反斜線後面可以跟隨各種字符來表示各種特殊序列。它也被用來轉義所有的元字符,所以你仍然可以在模式中匹配它們;例如,如果您需要匹配[\,則可以在它們前面加上反斜槓以刪除它們的特殊含義:\[\\

所以print(re.search('\d', '\d'))None因爲\d匹配任何十進制數字,但有沒有在\d

我現在預計print(re.search('\\d', '\d'))匹配\d但答案仍然是None

只有print(re.search('\\\d', '\d'))給出輸出<_sre.SRE_Match object; span=(0, 2), match='\\d'>

有人有解釋嗎?

+0

http://stackoverflow.com/questions/24085680/why-do-backslashes-appear-twice – fghj

+0

可能重複[無法用正則表達式逃避反斜槓?](https://stackoverflow.com/questions/4025482/無法使用正則表達式反斜槓) – tripleee

回答

8

令人困惑的是,反斜槓字符\被用作兩個不同級別的轉義。首先,在re模塊看到您的字符串之前,Python解釋器本身會執行\的替換。例如,\n轉換爲換行符,\t轉換爲製表符等。要獲得實際的\字符,您也可以將其轉義,因此\\只能提供一個\字符。如果\後面的字符不是公認的轉義字符,那麼\就像任何其他字符一樣對待並通過,但我不建議依賴此字符。相反,總是逃避你的\字符通過加倍,即\\

如果你想看看Python如何擴展你的字符串轉義,只需打印出字符串。例如:

s = 'a\\b\tc' 
print s 

如果s是聚合數據類型,例如的一部分一個列表或一個元組,並且如果你打印該聚集,Python將把該字符串用單引號括起來,幷包含\轉義符(以規範形式),所以要注意你的字符串是如何被打印的。如果你只是在解釋器中鍵入一個帶引號的字符串,它也會用'\'轉義符將其顯示在引號中。

一旦你知道你的字符串是如何編碼的,你就可以考慮一下re模塊將如何處理它。例如,如果您想通過re模塊將\轉換爲字符串,則需要將\\更改爲re,這意味着您需要在引用的Python字符串中使用\\\\。 Python字符串將以\\結尾,re模塊會將其視爲單個字面\字符。

在Python字符串中包含\字符的另一種方法是使用原始字符串,例如, r'a\b'相當於"a\\b"

+0

非常感謝所有的答案。我意識到r'...'並且通過了re的文檔,但是我沒有明白這一點。現在情況好轉了。 '\ b'對於python解釋器是特別的,因爲它找到'\'。 '\\ b'克服了以'\ b'結尾的python解釋器的解釋。這被re模塊識別爲十進制數字的快捷鍵。 '\\\ b'也克服了re模塊的解釋,我們最終得到字符串'\ b'。 – tobmei05

+0

謝謝! 4反斜槓,多好。所以在Python中沒有文字字符串?我的意思是在PHP中,例如,如果您使用單引號,則不會進行替換。 – Rolf

3

Python自己的字符串解析(部分)來自你的方式。

如果你想看到re看到的,在Python的命令提示符下鍵入

print '\d' 
print '\\d' 
print '\\\d' 

。您看到\d\\d都導致\d,後者由Python字符串解析器處理。

如果您想避免任何麻煩,請使用re module documentation建議的原始字符串:r'\\d'將導致\\d由RE模塊看到。

+2

https://docs.python.org/2/library/re.html請參閱'\'部分 – Alex

+1

@Alex謝謝,添加了答案的鏈接。 – glglgl

4

正則表達式之前的r字符在調用search()時指示正則表達式是原始字符串。這允許反斜槓在正則表達式中用作常規字符而不是字符的轉義序列。讓我解釋一下......

在re模塊的搜索方法處理傳遞給它的字符串之前,Python解釋器首先傳遞字符串。如果字符串中存在反斜槓,Python解釋器必須確定每個是否是Python轉義序列的一部分(例如\ n或\ t)。

注意:此時Python不關心'\'是否是正則表達式元字符。

如果'\'後面緊跟一個可識別的Python轉義字符(t,n等),則反斜槓和轉義字符將被替換爲實際的Unicode或8位字符。例如,'\ t'將替換爲製表符的ASCII字符。否則它會被傳遞並解釋爲'\'字符。

請考慮以下情況。

>>> s = '\t' 
>>> print ("[" + s + "]") 
>>> [  ]   // an actual tab character after preprocessing 

>>> s = '\d' 
>>> print ("[" + s + "]") 
>>> [\d]    // '\d' after preprocessing 

有時候,我們希望在一個字符串包括包含字符序列「\」而不會被Python的解釋爲轉義序列。要做到這一點,我們用'\'來避開'\'。現在,當Python看到'\'時,它將用一個'\'字符替換兩個反斜槓。

>>> s = '\\t' 
>>> print ("[" + s + "]") 
>>> [\t]    // '\t' after preprocessing 

在Python解釋器對這兩個字符串進行傳遞之後,它們被傳遞給re模塊的搜索方法。搜索方法分析正則表達式字符串以標識正則表達式的元字符。

現在'\'也是一個特殊的正則表達式元字符,並被解釋爲一個,除非在執行re search()方法時被轉義。

請考慮以下調用。

>>> match = re.search('a\\t','a\\t')  //Match is None 

這裏,匹配是無。爲什麼?讓我們看看Python解釋器通過後的字符串。

String 1: 'a\t' 
String 2: 'a\t' 

那麼爲什麼匹配等於無?當search()解釋字符串1時,由於它是一個正則表達式,反斜槓被解釋爲元字符,而不是普通字符。然而,字符串2中的反斜槓不是正則表達式,並且已經由Python解釋器處理,所以它被解釋爲普通字符。

因此,search()方法正在尋找字符串'a \ t'中不匹配的'escape-t'。

爲了解決這個問題,我們可以告訴search()方法不要將'\'解釋爲元字符。我們可以通過轉義來做到這一點。

請考慮以下調用。

>>> match = re.search('a\\\\t','a\\t')   // Match contains 'a\t' 

再次,讓我們看看Python解釋器通過後的字符串。

String 1: 'a\\t' 
String 2: 'a\t' 

現在,當search()方法處理該正則表達式,它看到第二反斜線由第一逃脫,而不應被認爲是元字符。因此,它將字符串解釋爲'a \ t',它與字符串2匹配。

將search()視爲字符的另一種方法是在正則表達式之前放置一個r。這告訴Python解釋器不要預處理字符串。

請考慮這一點。

>>> match = re.search(r'a\\t','a\\t')   // match contains 'a\t' 

這裏的Python解釋器不會修改第一個字符串,但會處理第二個字符串。 ()傳遞到查詢的字符串是:

String 1: 'a\\t' 
String 2: 'a\t' 

如在先前的例子中,搜索解釋「\」爲單個字符「\」,而不是一個元字符,因此與字符串2

匹配
相關問題