Python regex - awalan r


88

Adakah yang bisa menjelaskan mengapa contoh 1 di bawah ini berfungsi, ketika rawalan tidak digunakan? Saya pikir rawalan harus digunakan setiap kali escape sequence digunakan. Contoh 2 dan contoh 3 menunjukkan hal ini.

# 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

Jawaban:


87

Karena \memulai urutan escape hanya jika merupakan urutan escape yang valid.

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


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

Kecuali ada awalan 'r' atau 'R', urutan escape dalam string diinterpretasikan menurut aturan yang serupa dengan yang digunakan oleh Standar C. Urutan escape yang dikenali adalah:

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

Jangan pernah mengandalkan string mentah untuk literal jalur, karena string mentah memiliki cara kerja bagian dalam yang agak aneh , yang diketahui telah menggigit orang di pantat:

Ketika awalan "r" atau "R" ada, karakter setelah garis miring terbalik disertakan dalam string tanpa perubahan, dan semua garis miring terbalik tertinggal di string. Misalnya, string literal r"\n"terdiri dari dua karakter: garis miring terbalik dan huruf kecil "n". Tanda kutip string bisa di-escape dengan garis miring terbalik, tetapi garis miring terbalik tetap ada di string; misalnya, r"\""adalah string literal valid yang terdiri dari dua karakter: garis miring terbalik dan tanda kutip ganda; r"\"bukan literal string yang valid (bahkan string mentah tidak boleh diakhiri dengan garis miring terbalik dalam jumlah ganjil). Secara khusus, string mentah tidak boleh diakhiri dengan satu garis miring terbalik (karena garis miring terbalik akan keluar dari karakter kutipan berikut). Perhatikan juga bahwa satu garis miring terbalik diikuti oleh baris baru diartikan sebagai dua karakter sebagai bagian dari string,

Untuk mengilustrasikan poin terakhir ini dengan lebih baik:

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

Sebagai perbaikan minor, '\s'(like r'\s') juga direpresentasikan sebagai '\\s', karena '\s'tidak dikenali sebagai escape sequence.
Massood Khaari

@MassoodKhaari Saya bersumpah bahwa hasilnya benar ketika saya menulis jawaban ini ... Diperbaiki.
Esteban Küber

1
8 tahun pasti membenarkan perubahan ajaib dalam perilaku python. : D
Massood Khaari

35

'r' berarti yang berikut ini adalah "string mentah", yaitu. karakter garis miring terbalik diperlakukan secara harfiah alih-alih menandakan perlakuan khusus dari karakter berikut.

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

begitu '\n'juga satu baris baru
dan r'\n'dua karakter - garis miring terbalik dan huruf 'n'
cara lain untuk menulisnya adalah '\\n'karena garis miring terbalik pertama lolos dari yang kedua

cara yang setara untuk menulis ini

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

adalah

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

Karena cara Python memperlakukan karakter yang bukan karakter escape yang valid, tidak semua garis miring terbalik ganda itu diperlukan - misalnya, '\s'=='\\s'namun hal yang sama tidak berlaku untuk '\b'dan '\\b'. Preferensi saya adalah eksplisit dan menggandakan semua garis miring terbalik.


5

Tidak semua urutan yang melibatkan garis miring terbalik adalah urutan pelarian. \tdan \f, misalnya, tetapi \stidak. Dalam literal string non-mentah, apa pun \yang bukan bagian dari urutan pelolosan hanya dipandang sebagai \:

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

\b adalah sebuah escape sequence, jadi contoh 3 gagal. (Dan ya, beberapa orang menganggap perilaku ini agak tidak menguntungkan.)


Persis. Meskipun, @JT, saya sarankan untuk menggunakan '\\ s' atau r '\ s', atau Anda mungkin akan secara tidak sengaja menemukan beberapa escape sequence yang tidak Anda inginkan.
Blair Conrad

Memang: selalu gunakan literal string mentah ketika Anda ingin string mengandung garis miring terbalik (berlawanan dengan sebenarnya menginginkan urutan escape.)
Thomas Wouters

@ Thomas: rmasih lolos dari beberapa urutan ketika mereka muncul di akhir string: r"\"tidak valid, untuk melakukan itu Anda harus melakukannya "\\". Jika Anda melakukannya r"\\", Anda mendapatkan \\ ( "\\\\"string) yang dicetak . Hati-hati dengan itu.
Esteban Küber

Ya, literal string mentah tidak boleh diakhiri dengan satu `` \ `.
Thomas Wouters

@ Blair / Thomas: terima kasih - ini adalah aturan umum yang saya ikuti yang membuat saya bingung sejak awal! ... semuanya jelas sekarang, terima kasih semuanya. Meskipun mengikuti aturan ini ... saat membaca pola dari file teks biasa, bagaimana pola diteruskan sebagai string literal mentah?
JT.


0

Lihat contoh di bawah ini:

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


print "123\n123"
#outputs>>>
123
123
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.