Python Regex - Präfix

88

Kann jemand erklären, warum Beispiel 1 unten funktioniert, wenn das rPräfix nicht verwendet wird? Ich dachte, das rPräfix muss verwendet werden, wenn Escape-Sequenzen verwendet werden. Beispiel 2 und Beispiel 3 zeigen dies.

# 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
JT.
quelle

Antworten:

87

Weil \Escape-Sequenzen nur beginnen, wenn sie gültige Escape-Sequenzen sind.

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


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

Sofern kein Präfix 'r' oder 'R' vorhanden ist, werden Escape-Sequenzen in Zeichenfolgen nach Regeln interpretiert, die denen von Standard C ähneln. Die erkannten Escape-Sequenzen sind:

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

Verlassen Sie sich niemals auf rohe Strings für Pfadliterale, da rohe Strings ein ziemlich eigenartiges Innenleben haben, von dem bekannt ist, dass es Menschen in den Arsch gebissen hat:

Wenn ein "r" - oder "R" -Präfix vorhanden ist, wird ein Zeichen nach einem Backslash unverändert in die Zeichenfolge aufgenommen, und alle Backslashes bleiben in der Zeichenfolge. Das Zeichenfolgenliteral r"\n"besteht beispielsweise aus zwei Zeichen: einem Backslash und einem Kleinbuchstaben "n". Anführungszeichen können mit einem Backslash maskiert werden, der Backslash bleibt jedoch in der Zeichenfolge. Beispiel: r"\""Ein gültiges Zeichenfolgenliteral, das aus zwei Zeichen besteht: einem Backslash und einem doppelten Anführungszeichen. r"\"ist kein gültiges String-Literal (selbst ein roher String kann nicht mit einer ungeraden Anzahl von Backslashes enden). Insbesondere kann eine rohe Zeichenfolge nicht mit einem einzelnen Backslash enden (da der Backslash dem folgenden Anführungszeichen entgehen würde). Beachten Sie auch, dass ein einzelner Backslash gefolgt von einem Zeilenumbruch als diese beiden Zeichen als Teil der Zeichenfolge interpretiert wird.

Um diesen letzten Punkt besser zu veranschaulichen:

>>> 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 '\\'
\
Esteban Küber
quelle
Als geringfügige Korrektur wird '\s'(wie r'\s') auch als dargestellt '\\s', da es sich '\s'nicht um eine erkannte Escape-Sequenz handelt.
Massood Khaari
@MassoodKhaari Ich würde schwören, dass die Ausgabe korrekt war, als ich diese Antwort schrieb ... Behoben.
Esteban Küber
1
8 Jahre rechtfertigen sicherlich die magische Veränderung des Python-Verhaltens. : D
Massood Khaari
34

das 'r' bedeutet, dass das Folgende eine "rohe Zeichenfolge" ist, dh. Backslash-Zeichen werden wörtlich behandelt, anstatt eine Sonderbehandlung des folgenden Zeichens zu bedeuten.

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

so '\n'ist ein einzelne Newline
und r'\n'ist zwei Zeichen - ein Schrägstrich und die Buchstaben ‚n‘ eine
andere Art und Weise , es wäre zu schreiben , '\\n'weil der erste Backslash die zweite entkommt

eine äquivalente Art, dies zu schreiben

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

ist

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

Aufgrund der Art und Weise, wie Python Zeichen behandelt, die keine gültigen Escape-Zeichen sind, sind nicht alle dieser doppelten Backslashes erforderlich - z. B. gilt dies '\s'=='\\s'jedoch nicht für '\b'und '\\b'. Ich bevorzuge es, explizit zu sein und alle Backslashes zu verdoppeln.

John La Rooy
quelle
5

Nicht alle Sequenzen mit Backslashes sind Escape-Sequenzen. \tund \fsind zum Beispiel aber \snicht. In einem nicht rohen String-Literal wird alles \, was nicht Teil einer Escape-Sequenz ist, als nur ein anderes angesehen \:

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

\b ist jedoch eine Escape-Sequenz, daher schlägt Beispiel 3 fehl. (Und ja, einige Leute halten dieses Verhalten für ziemlich unglücklich.)

Thomas Wouters
quelle
Genau. Obwohl, @JT, ich die Verwendung von '\\ s' oder r '\ s' empfehle, werden Sie wahrscheinlich versehentlich einige Escape-Sequenzen treffen, die Sie nicht wollten.
Blair Conrad
In der Tat: Verwenden Sie immer rohe String-Literale, wenn der String Backslashes enthalten soll (im Gegensatz zu den Escape-Sequenzen).
Thomas Wouters
@Thomas: rentgeht immer noch einigen Sequenzen, wenn sie am Ende der Zeichenfolge erscheinen: r"\"ist ungültig, um das zu tun, müssen Sie tun "\\". Wenn Sie dies tun r"\\", erhalten Sie eine \\ gedruckte ( "\\\\"Zeichenfolge). Sei vorsichtig damit.
Esteban Küber
Ja, rohe String-Literale können nicht mit einem einzigen "\" enden.
Thomas Wouters
@ Blair / Thomas: Danke - das war die allgemeine Regel, die ich befolgt habe und die mich überhaupt verwirrt hat! ... jetzt ist alles klar, danke an alle. Wenn Sie diese Regel befolgen ... wie würde das Muster beim Lesen des Musters aus einer Nur-Text-Datei als rohe Literalzeichenfolge weitergegeben?
JT.
0

Versuch das:

a = '\''
'
a = r'\''
\'
a = "\'"
'
a = r"\'"
\'
user2856064
quelle
0

Überprüfen Sie das folgende Beispiel:

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


print "123\n123"
#outputs>>>
123
123
Ugur Umut
quelle