Python regex - r คำนำหน้า


89

ใครช่วยอธิบายrได้ไหมว่าทำไมตัวอย่างที่ 1 ด้านล่างใช้งานได้เมื่อไม่ได้ใช้คำนำหน้า ฉันคิดว่าrต้องใช้คำนำหน้าทุกครั้งที่ใช้ลำดับการหลีกเลี่ยง ตัวอย่างที่ 2 และตัวอย่างที่ 3 แสดงให้เห็นถึงสิ่งนี้

# 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

คำตอบ:


88

เนื่องจาก\เริ่มลำดับการหลบหนีก็ต่อเมื่อเป็นลำดับการหลีกเลี่ยงที่ถูกต้อง

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


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

เว้นแต่จะมีคำนำหน้า 'r' หรือ 'R' ลำดับการหลีกเลี่ยงในสตริงจะถูกตีความตามกฎที่คล้ายกับที่ใช้โดย Standard C ลำดับการหลีกเลี่ยงที่รู้จัก ได้แก่ :

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

อย่าพึ่งพาสตริงดิบสำหรับตัวอักษรเส้นทางเนื่องจากสตริงดิบมีการทำงานภายในที่ค่อนข้างแปลกประหลาดซึ่งทราบกันดีว่าได้กัดคนในตูด:

เมื่อมีคำนำหน้า "r" หรือ "R" อักขระที่ตามหลังเครื่องหมายแบ็กสแลชจะรวมอยู่ในสตริงโดยไม่มีการเปลี่ยนแปลงและแบ็กสแลชทั้งหมดจะเหลืออยู่ในสตริง ตัวอย่างเช่นสตริงลิเทอรัลr"\n"ประกอบด้วยอักขระสองตัว ได้แก่ แบ็กสแลชและตัวพิมพ์เล็ก "n" คำพูดสตริงสามารถหลีกเลี่ยงได้โดยใช้แบ็กสแลช แต่แบ็กสแลชยังคงอยู่ในสตริง ตัวอย่างเช่นr"\""เป็นลิเทอรัลสตริงที่ถูกต้องซึ่งประกอบด้วยอักขระสองตัว: แบ็กสแลชและเครื่องหมายคำพูดคู่ r"\"ไม่ใช่สตริงลิเทอรัลที่ถูกต้อง (แม้แต่สตริงดิบก็ไม่สามารถลงท้ายด้วยแบ็กสแลชจำนวนคี่ได้) โดยเฉพาะสตริงดิบไม่สามารถลงท้ายด้วยแบ็กสแลชเดียว (เนื่องจากแบ็กสแลชจะหนีอักขระเครื่องหมายคำพูดต่อไปนี้) โปรดทราบด้วยว่าแบ็กสแลชเดียวตามด้วยขึ้นบรรทัดใหม่ถูกตีความว่าอักขระสองตัวนั้นเป็นส่วนหนึ่งของสตริง

เพื่ออธิบายประเด็นสุดท้ายนี้ให้ดีขึ้น:

>>> 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 '\\'
\

ในฐานะการแก้ไขเล็กน้อย'\s'(like r'\s') ยังแสดงเป็น'\\s'เนื่องจาก'\s'ไม่ใช่ลำดับการหลีกเลี่ยงที่รู้จัก
Massood Khaari

@MassoodKhaari ฉันขอสาบานว่าผลลัพธ์นั้นถูกต้องเมื่อฉันเขียนคำตอบนี้ ...
Esteban Küber

1
8 ปีแสดงให้เห็นถึงการเปลี่ยนแปลงที่น่าอัศจรรย์ในพฤติกรรมของงูหลาม : D
Massood Khaari

35

'r' หมายถึงสิ่งต่อไปนี้คือ "สตริงดิบ" เช่น อักขระแบ็กสแลชจะได้รับการปฏิบัติตามตัวอักษรแทนที่จะแสดงถึงการปฏิบัติพิเศษของอักขระต่อไปนี้

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

ดังนั้นจึง'\n'เป็นบรรทัดใหม่เดียว
และr'\n'มีอักขระสองตัว - แบ็กสแลชและตัวอักษร 'n'
อีกวิธีหนึ่งในการเขียนมันอาจเป็น'\\n'เพราะแบ็กสแลชตัวแรกหนีตัวที่สอง

วิธีที่เทียบเท่ากันในการเขียนสิ่งนี้

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'))

เนื่องจากวิธีหลามตัวละครถือว่าที่ไม่ได้เป็นตัวละครที่ถูกต้องหลบหนีไม่ทั้งหมดของ backslashes คู่เหล่านั้นเป็นสิ่งที่จำเป็น - เช่น'\s'=='\\s'แต่เดิมไม่เป็นความจริงสำหรับและ'\b' '\\b'ความชอบของฉันคือชัดเจนและเพิ่มแบ็กสแลชทั้งหมดเป็นสองเท่า


6

ไม่ใช่ลำดับทั้งหมดที่เกี่ยวข้องกับแบ็กสแลชเป็นลำดับ Escape \tและ\fเป็นตัวอย่างเช่น แต่\sไม่ใช่ ในลิเทอรัลสตริงที่ไม่ใช่ดิบสิ่ง\ที่ไม่ได้เป็นส่วนหนึ่งของลำดับการหลีกเลี่ยงจะถูกมองว่าเป็นอีกแบบหนึ่ง\:

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

\b เป็นลำดับการหลีกเลี่ยงอย่างไรก็ตามตัวอย่างที่ 3 ล้มเหลว (และใช่บางคนคิดว่าพฤติกรรมนี้ค่อนข้างโชคร้าย)


ตรง แม้ว่า @JT ฉันขอแนะนำให้ใช้ '\\ s' หรือ r '\ s' ไม่เช่นนั้นคุณอาจจะเข้าสู่ลำดับการหลีกเลี่ยงบางอย่างที่คุณไม่ได้ตั้งใจโดยไม่ได้ตั้งใจ
Blair Conrad

แท้จริง: ใช้ตัวอักษรสตริงดิบเสมอเมื่อคุณต้องการให้สตริงมีแบ็กสแลช (ซึ่งตรงข้ามกับการต้องการลำดับการหลบหนีจริงๆ)
Thomas Wouters

@ โทมัส: rยังคงหลบหนีบางลำดับเมื่อปรากฏที่ท้ายสตริง: r"\"ไม่ถูกต้องคุณต้องทำเช่น"\\"นั้น ถ้าคุณทำr"\\"คุณจะได้รับ\\ พิมพ์ ( "\\\\"สตริง) ระวังด้วยนะ
Esteban Küber

ใช่ตัวอักษรสตริงดิบไม่สามารถลงท้ายด้วย "\"
Thomas Wouters

@ แบลร์ / โทมัส: ขอบคุณ - นี่เป็นกฎทั่วไปที่ฉันปฏิบัติตามซึ่งทำให้ฉันสับสนตั้งแต่แรก! ... ตอนนี้ชัดเจนแล้วขอบคุณทุกคน แม้ว่าจะปฏิบัติตามกฎนี้ ... เมื่ออ่านรูปแบบจากไฟล์ข้อความธรรมดารูปแบบจะถูกส่งต่อเป็นสตริงลิเทอรัลดิบได้อย่างไร
.


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.