Tiền tố regex - r trong Python


87

Bất cứ ai có thể giải thích tại sao ví dụ 1 dưới đây hoạt động, khi rtiền tố không được sử dụng? Tôi nghĩ rằng rtiền tố phải được sử dụng bất cứ khi nào các chuỗi thoát được sử dụng. Ví dụ 2 và ví dụ 3 chứng minh điều này.

# example 1
import re
print (re.sub('\s+', ' ', 'hello     there      there'))
# prints 'hello there there' - not expected as r prefix is not used

# example 2
import re
print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello     there      there'))
# prints 'hello     there' - as expected as r prefix is used

# example 3
import re
print (re.sub('(\b\w+)(\s+\1\b)+', '\1', 'hello     there      there'))
# prints 'hello     there      there' - as expected as r prefix is not used

Câu trả lời:


86

Vì chỉ \bắt đầu trình tự thoát khi chúng là trình tự thoát hợp lệ.

>>> '\n'
'\n'
>>> r'\n'
'\\n'
>>> print '\n'


>>> print r'\n'
\n
>>> '\s'
'\\s'
>>> r'\s'
'\\s'
>>> print '\s'
\s
>>> print r'\s'
\s

Trừ khi có tiền tố 'r' hoặc 'R', chuỗi thoát trong chuỗi được diễn giải theo các quy tắc tương tự như các quy tắc được sử dụng bởi Tiêu chuẩn C. Các chuỗi thoát được công nhận là:

Escape Sequence   Meaning Notes
\newline  Ignored  
\\    Backslash (\)    
\'    Single quote (')     
\"    Double quote (")     
\a    ASCII Bell (BEL)     
\b    ASCII Backspace (BS)     
\f    ASCII Formfeed (FF)  
\n    ASCII Linefeed (LF)  
\N{name}  Character named name in the Unicode database (Unicode only)  
\r    ASCII Carriage Return (CR)   
\t    ASCII Horizontal Tab (TAB)   
\uxxxx    Character with 16-bit hex value xxxx (Unicode only) 
\Uxxxxxxxx    Character with 32-bit hex value xxxxxxxx (Unicode only) 
\v    ASCII Vertical Tab (VT)  
\ooo  Character with octal value ooo
\xhh  Character with hex value hh

Đừng bao giờ dựa vào các chuỗi thô cho các ký tự đường dẫn, vì các chuỗi thô có một số hoạt động bên trong khá đặc biệt , được biết là đã cắn người vào mông:

Khi có tiền tố "r" hoặc "R", một ký tự theo sau dấu gạch chéo ngược được bao gồm trong chuỗi mà không thay đổi và tất cả các dấu gạch chéo ngược được để lại trong chuỗi. Ví dụ: chuỗi ký tự r"\n"bao gồm hai ký tự: dấu gạch chéo ngược và chữ thường "n". Dấu ngoặc kép của chuỗi có thể được thoát bằng dấu gạch chéo ngược, nhưng dấu gạch chéo ngược vẫn còn trong chuỗi; ví dụ, r"\""là một chuỗi ký tự hợp lệ bao gồm hai ký tự: dấu gạch chéo ngược và dấu ngoặc kép; r"\"không phải là một chuỗi hợp lệ theo nghĩa đen (ngay cả một chuỗi thô không thể kết thúc bằng một số lẻ dấu gạch chéo ngược). Cụ thể, một chuỗi thô không thể kết thúc bằng một dấu gạch chéo ngược (vì dấu gạch chéo ngược sẽ thoát khỏi ký tự trích dẫn sau). Cũng lưu ý rằng một dấu gạch chéo ngược đơn theo sau bởi một dòng mới được hiểu là hai ký tự đó là một phần của chuỗi,

Để minh họa rõ hơn điểm cuối cùng này:

>>> r'\'
SyntaxError: EOL while scanning string literal
>>> r'\''
"\\'"
>>> '\'
SyntaxError: EOL while scanning string literal
>>> '\''
"'"
>>> 
>>> r'\\'
'\\\\'
>>> '\\'
'\\'
>>> print r'\\'
\\
>>> print r'\'
SyntaxError: EOL while scanning string literal
>>> print '\\'
\

Như một sửa chữa nhỏ, '\s'(like r'\s') cũng được biểu thị là '\\s', do '\s'không phải là một chuỗi thoát được công nhận.
Massood Khaari

@MassoodKhaari Tôi thề rằng đầu ra đã chính xác trở lại khi tôi viết câu trả lời này ... Đã sửa.
Esteban Küber

1
8 năm chắc chắn biện minh cho sự thay đổi kỳ diệu trong hành vi của trăn. : D
Massood Khaari

34

'r' có nghĩa là sau đây là một "chuỗi thô", tức là. các ký tự gạch chéo ngược được xử lý theo nghĩa đen thay vì biểu thị cách xử lý đặc biệt của ký tự sau.

http://docs.python.org/reference/lexical_analysis.html#literals

vì thế '\n'là một dòng mới nhất
r'\n'là hai nhân vật - một dấu chéo ngược và chữ 'n'
một cách khác để viết nó sẽ là '\\n'vì xuyệc ngược đầu tiên thoát thứ hai

một cách tương đương để viết cái này

print (re.sub(r'(\b\w+)(\s+\1\b)+', r'\1', 'hello     there      there'))

print (re.sub('(\\b\\w+)(\\s+\\1\\b)+', '\\1', 'hello     there      there'))

Do cách Python xử lý các ký tự không phải là ký tự thoát hợp lệ, không phải tất cả các dấu gạch chéo ngược kép đó đều cần thiết - ví dụ: '\s'=='\\s'tuy nhiên điều tương tự không đúng đối với '\b''\\b'. Sở thích của tôi là rõ ràng và nhân đôi tất cả các dấu gạch chéo ngược.


5

Không phải tất cả các chuỗi liên quan đến dấu gạch chéo ngược đều là chuỗi thoát. \t\flà, ví dụ, nhưng \skhông phải. Trong một ký tự không phải là chuỗi thô, bất kỳ chuỗi nào \không phải là một phần của chuỗi thoát đều được coi là một chuỗi khác \:

>>> "\s"
'\\s'
>>> "\t"
'\t'

\b một chuỗi thoát, tuy nhiên, vì vậy ví dụ 3 không thành công. (Và vâng, một số người coi hành vi này là khá đáng tiếc.)


Chính xác. Mặc dù, @JT, tôi khuyên bạn nên sử dụng '\\ s' hoặc r '\ s', nếu không bạn có thể vô tình gặp phải một số chuỗi thoát mà bạn không cố ý.
Blair Conrad

Thật vậy: luôn luôn sử dụng xâu liệu khi bạn muốn chuỗi để chứa những dấu xồ nguợc (như trái ngược với thực tế muốn chuỗi thoát.)
Thomas Wouters

@Thomas: rvẫn thoát một số chuỗi khi chúng xuất hiện ở cuối chuỗi: r"\"không hợp lệ, để làm điều đó bạn phải làm "\\". Nếu bạn làm vậy r"\\", bạn sẽ nhận được một \\ ( "\\\\"chuỗi) được in . Hãy cẩn thận với điều đó.
Esteban Küber

Có, các ký tự chuỗi thô không thể kết thúc bằng một dấu `\ '.
Thomas Wouters

@ Blair / Thomas: cảm ơn - đây là quy tắc chung mà tôi đã tuân theo khiến tôi bối rối ngay từ đầu! ... tất cả đã rõ ràng bây giờ, cảm ơn tất cả. Mặc dù theo quy tắc này ... khi đọc mẫu từ tệp văn bản thuần túy, mẫu sẽ được chuyển như thế nào dưới dạng một chuỗi chữ thô?
JT.


0

Kiểm tra ví dụ dưới đây:

print r"123\n123" 
#outputs>>>
123\n123


print "123\n123"
#outputs>>>
123
123
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.