2015-11-07 24 views
8

Tôi bị nhầm lẫn với dấu gạch chéo ngược trong cụm từ thông dụng. Trong một regex, \ có ý nghĩa đặc biệt, ví dụ: \d có nghĩa là một chữ số thập phân. Nếu bạn thêm dấu gạch chéo ngược ở phía trước dấu gạch chéo ngược thì ý nghĩa đặc biệt này sẽ bị mất. Trong số regex-howto người ta có thể đọc:Dấu gạch chéo ngược trong Python Biểu thức chính quy

Có lẽ metacharacter quan trọng nhất là dấu gạch chéo ngược, \. Như trong các chuỗi ký tự chuỗi Python, dấu gạch chéo ngược có thể được theo sau bởi các ký tự khác nhau để báo hiệu các chuỗi đặc biệt khác nhau. Nó cũng được sử dụng để thoát khỏi tất cả các siêu ký tự sao cho bạn vẫn có thể phù hợp với chúng trong các mẫu; ví dụ: nếu bạn cần khớp với một số [ hoặc \, bạn có thể đặt trước dấu gạch chéo ngược để xóa nghĩa đặc biệt của chúng: \[ hoặc \\.

Vì vậy print(re.search('\d', '\d')) cho None\d khớp với bất kỳ chữ số thập phân nhưng chẳng có ai trong \d.

Tôi mong đợi print(re.search('\\d', '\d')) để khớp với \d nhưng câu trả lời vẫn là None.

Chỉ print(re.search('\\\d', '\d')) cho đầu ra <_sre.SRE_Match object; span=(0, 2), match='\\d'>.

Có ai đó có giải thích không?

+0

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

+0

Có thể trùng lặp của [Không thể thoát khỏi dấu gạch chéo ngược với regex?] (Https://stackoverflow.com/questions/4025482/ cant-escape-the-backslash-with-regex) – tripleee

Trả lời

8

Sự nhầm lẫn là do thực tế là ký tự dấu chéo ngược \ được sử dụng làm lối thoát ở hai cấp độ khác nhau. Đầu tiên, trình thông dịch Python tự thực hiện các thay thế cho \ trước khi mô-đun re từng thấy chuỗi của bạn. Ví dụ: \n được chuyển thành ký tự dòng mới, \t được chuyển thành ký tự tab, v.v. Để nhận được ký tự \ thực, bạn cũng có thể thoát khỏi ký tự đó, vì vậy, \\ chỉ cho một ký tự \. Nếu ký tự theo sau \ không phải là ký tự thoát được nhận dạng, thì \ được xử lý giống như bất kỳ ký tự nào khác và được chuyển qua, nhưng tôi không khuyên bạn nên tùy thuộc vào điều này. Thay vào đó, luôn luôn thoát khỏi các ký tự \ của bạn bằng cách nhân đôi chúng, tức là \\.

Nếu bạn muốn xem Python đang mở rộng chuỗi của bạn như thế nào, chỉ cần in ra chuỗi. Ví dụ:

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

Nếu s là một phần của loại dữ liệu tổng hợp, ví dụ:một danh sách hoặc một bộ tuple, và nếu bạn in tổng hợp đó, Python sẽ kèm theo chuỗi trong dấu nháy đơn và sẽ bao gồm các số thoát \ (ở dạng kinh điển), vì vậy hãy lưu ý cách chuỗi của bạn đang được in. Nếu bạn chỉ cần nhập một chuỗi được trích dẫn vào trình thông dịch, nó cũng sẽ hiển thị nó kèm theo dấu ngoặc kép với '\' thoát.

Khi bạn biết chuỗi của mình đang được mã hóa như thế nào, bạn có thể nghĩ về mô-đun re sẽ làm gì với nó. Ví dụ: nếu bạn muốn thoát khỏi \ trong chuỗi bạn chuyển đến mô-đun re, bạn sẽ cần phải vượt qua \\ đến re, có nghĩa là bạn sẽ cần sử dụng \\\\ trong chuỗi Python được trích dẫn của mình. Chuỗi Python sẽ kết thúc với \\ và mô-đun re sẽ coi đây là một ký tự \.

Một cách khác để bao gồm \ ký tự trong chuỗi Python là sử dụng chuỗi thô, ví dụ: r'a\b' tương đương với "a\\b".

+0

Cảm ơn rất nhiều cho tất cả các câu trả lời.Tôi đã nhận thức được r '...' và cũng đã đi qua các tài liệu của lại nhưng tôi đã không nhận được điểm. Bây giờ mọi thứ tốt hơn. '\ b' đặc biệt cho trình thông dịch python vì nó tìm thấy '\'. '\\ b' vượt qua sự giải thích của trình thông dịch python kết thúc bằng một chuỗi '\ b'. Điều này được nhận biết bởi mô-đun sẽ là phím tắt cho một chữ số thập phân. '\\\ b' cũng vượt qua sự giải thích của mô-đun tái và chúng ta kết thúc bằng chuỗi '\ b'. – tobmei05

+0

Cảm ơn bạn! 4 dấu gạch chéo ngược, đẹp như thế nào. Vì vậy, không có chuỗi chữ trong python? Tôi có nghĩa là trong PHP, ví dụ, nếu bạn sử dụng dấu nháy đơn thì không có thay thế được thực hiện. – Rolf

3

Phân tích cú pháp chuỗi riêng của Python (một phần) xuất hiện theo cách của bạn.

Nếu bạn muốn xem những gì re thấy, loại

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

trên cửa sổ lệnh Python. Bạn thấy rằng \d\\d cả hai kết quả là \d, cái thứ hai được đưa ra bởi trình phân tích cú pháp chuỗi Python.

Nếu bạn muốn tránh bất kỳ sự phức tạp nào, hãy sử dụng chuỗi thô theo đề xuất của re module documentation: r'\\d' sẽ dẫn đến mô-đun RE được xem là \\d.

+2

https://docs.python.org/2/library/re.html xem phần '\' – Alex

+1

@Alex Cảm ơn, đã thêm liên kết vào câu trả lời. – glglgl

4

Ký tự r trước biểu thức chính quy cho biết trong lệnh gọi để tìm kiếm() chỉ định biểu thức chính quy là chuỗi thô. Điều này cho phép dấu gạch chéo ngược được sử dụng trong cụm từ thông dụng dưới dạng ký tự thông thường thay vì trong chuỗi ký tự thoát. Hãy để tôi giải thích ...

Trước khi phương thức tìm kiếm của mô-đun tìm lại xử lý các chuỗi được truyền cho nó, trình thông dịch Python lấy một dấu đầu tiên trên chuỗi. Nếu có dấu gạch chéo ngược có trong chuỗi, trình thông dịch Python phải quyết định xem mỗi bộ phận có phải là một phần của chuỗi thoát Python (ví dụ: \ n hoặc \ t) hay không.

Lưu ý: tại thời điểm này, Python không quan tâm liệu '\' có phải là ký tự meta biểu thức chính quy hay không.

Nếu '\' được theo sau bởi một ký tự thoát Python được nhận dạng (t, n, v.v.), thì dấu gạch chéo ngược và ký tự thoát được thay thế bằng ký tự Unicode hoặc 8 bit thực tế. Ví dụ: '\ t' sẽ được thay thế bằng ký tự ASCII cho tab. Nếu không, nó sẽ được thông qua và được hiểu là ký tự '\'.

Hãy xem xét những điều sau đây.

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

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

Thỉnh thoảng, chúng tôi muốn đưa vào chuỗi một chuỗi ký tự bao gồm '\' mà không cần Python hiểu là trình tự thoát. Để làm điều này, chúng ta thoát khỏi '\' bằng '\'. Bây giờ khi Python thấy '\' nó thay thế hai dấu gạch chéo ngược bằng một ký tự '\' duy nhất.

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

Sau khi trình thông dịch Python truyền qua cả hai chuỗi, chúng được chuyển sang phương pháp tìm kiếm của mô-đun. Phương thức tìm kiếm phân tích chuỗi biểu thức chính quy để xác định các ký tự meta của cụm từ thông dụng.

Bây giờ '\' cũng là ký tự meta biểu thức chính quy đặc biệt và được hiểu là một UNLESS nó được thoát tại thời điểm phương thức tìm kiếm lại() được thực hiện.

Xem xét cuộc gọi sau.

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

Tại đây, đối sánh là Không. Tại sao? Cho phép xem xét các chuỗi sau khi trình thông dịch Python thực hiện.

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

Vậy tại sao khớp bằng Không?Khi tìm kiếm() diễn giải chuỗi 1, vì nó là một biểu thức chính quy, dấu gạch chéo ngược được hiểu là ký tự meta, không phải là ký tự bình thường. Dấu gạch chéo ngược trong Chuỗi 2 tuy nhiên không có biểu thức chính quy và đã được xử lý bởi trình thông dịch Python, vì vậy nó được hiểu là ký tự thông thường.

Vì vậy, phương thức search() đang tìm 'escape-t' trong chuỗi 'a \ t' không khớp.

Để khắc phục điều này, chúng tôi có thể yêu cầu phương thức search() không diễn giải '\' làm siêu ký tự. Chúng ta có thể làm điều này bằng cách thoát nó.

Xem xét cuộc gọi sau.

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

Một lần nữa, hãy xem các chuỗi sau khi trình thông dịch Python đã vượt qua.

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

Bây giờ khi phương thức search() xử lý cụm từ thông dụng, nó phát hiện dấu gạch chéo ngược thứ hai được thoát bởi dấu đầu tiên và không được coi là ký tự meta. Do đó, nó giải thích chuỗi là 'a \ t', khớp với Chuỗi 2.

Một cách khác để tìm kiếm() xem '\' như một ký tự là đặt dấu r trước biểu thức chính quy. Điều này báo cho trình thông dịch Python KHÔNG xử lý trước chuỗi.

Hãy xem xét điều này.

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

Tại đây trình thông dịch Python không sửa đổi chuỗi đầu tiên nhưng xử lý chuỗi thứ hai. Các chuỗi thông qua để tìm kiếm() là:

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

Như trong ví dụ trước, tìm kiếm diễn giải '\' là ký tự đơn '\' và không phải là một siêu nhân vật, do đó phù hợp với String 2.

Các vấn đề liên quan