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

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

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.


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


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

Überprüfen Sie das folgende Beispiel:

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


print "123\n123"
#outputs>>>
123
123
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.