Python正規表現-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'プレフィックスが存在しない限り、文字内のエスケープシーケンスは、標準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」の2文字で構成されます。文字列の引用符はバックスラッシュでエスケープできますが、バックスラッシュは文字列に残ります。たとえば、r"\""バックスラッシュと二重引用符の2文字で構成される有効な文字列リテラルです。r"\"は有効な文字列リテラルではありません(生の文字列でさえ奇数の円記号で終了することはできません)。具体的には、生の文字列を単一の円記号で終了することはできません(円記号は次の引用文字をエスケープするため)。また、1つの円記号とそれに続く改行は、文字列の一部としてこれら2つの文字として解釈されることにも注意してください。

この最後の点をよりよく説明するために:

>>> 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'(のようなr'\s')も、認識されたエスケープシーケンスではない'\\s'ため、として表され'\s'ます。
Massood Khaari 2018

@MassoodKhaariこの回答を書いたとき、出力が正しかったことを誓います...修正されました。
エステバンKüber

1
8年は確かにPythonの振る舞いの魔法の変化を正当化します。:D
Massood Khaari 2018

35

'r'は、以下が「生の文字列」であることを意味します。バックスラッシュ文字は、次の文字の特別な扱いを意味するのではなく、文字通りに扱われます。

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

その'\n'単一の改行がある
r'\n'バックスラッシュと文字「N」 - 2つの文字で
それを書くために別の方法は次のようになり'\\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'))

例えば-すべてではないそれらの二重のバックスラッシュの、有効なエスケープ文字ではありませんPythonの扱いの文字が必要な方法のため、'\s'=='\\s'同じことが当てはまりませんしかし、'\b''\\b'。私の好みは、明示的で、すべての円記号を2倍にすることです。


6

バックスラッシュを含むすべてのシーケンスがエスケープシーケンスであるとは限りません。\tそして\f例えば、ですが、\sではありません。非生の文字列リテラルで\は、エスケープシーケンスの一部ではないものは、単なる別のものと見なされます\

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

\b ですが、エスケープシーケンスなので、例3は失敗します。(そして、はい、一部の人々はこの振る舞いをかなり不幸だと考えています。)


丁度。ただし、@ JTでは、「\\ s」または「r」\ s 'を使用することをお勧めします。そうしないと、意図しないエスケープシーケンスが誤ってヒットする可能性があります。
ブレアコンラッド

確かに:あなたは文字列にバックスラッシュを入れたいときは、常に生の文字列リテラルを使用します(実際にはエスケープシーケンスを望むとは対照的である。)
トーマス・WOUTERS

@Thomas:r文字列の最後に表示される場合でも、一部のシーケンスをエスケープします:r"\"無効です"\\"。これを行うには、実行する必要があります。あなたが行う場合はr"\\"、あなたが得る\\ 印刷("\\\\"文字列)。それに注意してください。
エステバンKüber

はい、生の文字列リテラルを単一の `\`で終わらせることはできません。
Thomas Wouters 2010

@ Blair / Thomas:ありがとう-これは私が従った一般的なルールであり、そもそも私を混乱させました!...すべてが明確になりました。ありがとうございます。このルールに従うと...プレーンテキストファイルからパターンを読み取る場合、パターンはどのように生のリテラル文字列として渡されますか?
JT。

0

それを試してください:

a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'

0

以下の例を確認してください。

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


print "123\n123"
#outputs>>>
123
123
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.