Python regex - r öneki


89

rÖnek kullanılmadığında aşağıdaki 1. örnek neden işe yarıyor ? rKaçış dizileri kullanıldığında önekin kullanılması gerektiğini düşündüm . Örnek 2 ve örnek 3 bunu göstermektedir.

# 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

Yanıtlar:


88

Çünkü \kaçış dizilerine yalnızca geçerli kaçış dizileri olduklarında başlayın.

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


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

Bir "r" veya "R" öneki olmadığı sürece , dizelerdeki kaçış dizileri Standart C tarafından kullanılanlara benzer kurallara göre yorumlanır. Tanınan kaçış dizileri şunlardır:

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

Yol değişmezleri için asla ham dizelere güvenmeyin, çünkü ham dizeler, insanları kıçından ısırdığı bilinen oldukça tuhafişleyişe sahiptir:

Bir "r" veya "R" öneki mevcut olduğunda, bir ters eğik çizgiyi takip eden bir karakter dizeye değişiklik yapılmadan eklenir ve tüm ters eğik çizgiler dizede bırakılır. Örneğin, dize değişmezi r"\n"iki karakterden oluşur: ters eğik çizgi ve küçük harf "n". Dize tırnak işaretleri ters eğik çizgiyle önlenebilir, ancak ters eğik çizgi dizede kalır; örneğin, r"\""iki karakterden oluşan geçerli bir dizedir: ters eğik çizgi ve çift tırnak;r"\"geçerli bir dize değişmezi değildir (ham bir dize bile tek sayıda ters eğik çizgi ile bitemez). Spesifik olarak, bir ham dize tek bir ters eğik çizgiyle bitemez (çünkü ters eğik çizgi aşağıdaki tırnak karakterinden kaçacaktır). Ayrıca, tek bir ters eğik çizgiyi takip eden bir satırsonu, bu iki karakterin dizenin parçası olarak yorumlandığını unutmayın,

Bu son noktayı daha iyi açıklamak için:

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

Küçük bir düzeltme olarak, '\s'(gibi r'\s') aynı zamanda şu şekilde temsil edilir '\\s'dolayı, '\s'bilinen bir çıkış sırası olmayan.
Massood Khaari

@MassoodKhaari Bu cevabı yazdığımda çıktının doğru olduğuna yemin ederim ... Düzeltildi.
Esteban Küber

1
8 yıl kesinlikle piton davranışındaki sihirli değişikliği haklı çıkarır. : D
Massood Khaari

35

'r', aşağıdakinin bir "ham dizge" olduğu anlamına gelir, yani. ters eğik çizgi karakterleri, aşağıdaki karakterin özel olarak ele alınması yerine tam anlamıyla ele alınır.

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

bu yüzden '\n'tek bir satırsonu
ve r'\n'iki karakterdir - ters eğik çizgi ve 'n' harfi,
bunu yazmanın başka bir yolu da'\\n' da ilk ters eğik çizginin ikinciden kaçmasıdır

bunu yazmanın eşdeğer bir yolu

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

dır-dir

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

Python'un geçerli kaçış karakterleri olmayan karakterleri işleme biçimi nedeniyle, bu çift ters eğik çizgilerin tümü gerekli değildir - örneğin '\s'=='\\s'aynı şey '\b've için geçerli değildir '\\b'. Tercihim açık olmak ve tüm ters eğik çizgileri iki katına çıkarmaktır.


6

Ters eğik çizgi içeren tüm diziler kaçış dizileri değildir. \tve \förneğin, ama \sdeğil. Ham olmayan bir dize değişmezinde, \bir kaçış dizisinin parçası olmayan herhangi biri başka biri olarak görülür \:

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

\b olduğu , örneğin 3 başarısız şekilde bir çıkış dizisi Ancak. (Ve evet, bazı insanlar bu davranışın oldukça talihsiz olduğunu düşünüyor.)


Kesinlikle. Yine de @JT, '\\ s' veya r '\ s' kullanmanızı öneririm, yoksa muhtemelen istemediğiniz bazı kaçış dizilerini yanlışlıkla vurursunuz.
Blair Conrad

Nitekim: Eğer dize ters eğik çizgi içermesini istediğiniz zaman hep çiğ dize hazır kullanmak (aslında çıkış sıralarını isteyen karşıt olarak.)
Thomas Wouters

@Thomas: rdizenin sonunda göründüklerinde bazı dizilerden hala kaçar: r"\"bunu yapmak için geçersizdir "\\". Bunu yaparsanız r"\\", \\ basılı bir ( "\\\\"dize) alırsınız . Buna dikkat et.
Esteban Küber

Evet, ham dize değişmezleri tek bir "\" ile bitemez.
Thomas Wouters

@ Blair / Thomas: teşekkürler - ilk başta kafamı karıştıran, takip ettiğim genel kural buydu! ... şimdi her şey açık, herkese teşekkürler. Yine de bu kuralı takip ederken ... düz bir metin dosyasından örüntü okurken, örüntü nasıl ham bir değişmez dizge olarak aktarılır?
JT.


0

Aşağıdaki örneği kontrol edin:

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


print "123\n123"
#outputs>>>
123
123
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.