Aus der Python-Dokumentation zu Regex bezüglich des '\'
Charakters:
Die Lösung besteht darin, die rohe String-Notation von Python für Muster mit regulären Ausdrücken zu verwenden. Backslashes werden in einem Zeichenfolgenliteral mit dem Präfix nicht speziell behandelt
'r'
. Sor"\n"
ist eine Zwei-Zeichenkette enthält'\'
und'n'
, während"\n"
ein Eins-Zeichenfolge eine neue Zeile enthält. Normalerweise werden Muster in Python-Code unter Verwendung dieser rohen Zeichenfolgennotation ausgedrückt.
Was ist diese rohe String-Notation? Wenn Sie ein Rohzeichenfolgenformat verwenden, bedeutet dies, dass "*"
es sich eher um ein Literal als um einen Null-oder-Mehr-Indikator handelt? Das kann natürlich nicht richtig sein, sonst würde Regex seine Kraft völlig verlieren. Aber wenn es sich um eine rohe Zeichenfolge handelt, wie erkennt es dann Zeilenumbrüche, wenn "\n"
es sich buchstäblich um einen Backslash und einen handelt "n"
?
Ich folge nicht.
Für Kopfgeld bearbeiten:
Ich versuche zu verstehen, wie ein Regex für rohe Zeichenfolgen mit Zeilenumbrüchen, Tabulatoren und Zeichensätzen übereinstimmt, z. B. \w
für Wörter oder \d
Ziffern oder so weiter, wenn rohe Zeichenfolgenmuster Backslashes nicht als etwas anderes als gewöhnliche Zeichen erkennen. Ich könnte wirklich einige gute Beispiele gebrauchen.
quelle
Antworten:
Zarkonnens Antwort beantwortet Ihre Frage, aber nicht direkt. Lassen Sie mich versuchen, direkter zu sein und zu sehen, ob ich das Kopfgeld von Zarkonnen bekommen kann.
Sie werden dies vielleicht leichter verstehen, wenn Sie die Begriffe "Raw String Regex" und "Raw String Patterns" nicht mehr verwenden. Diese Begriffe verbinden zwei separate Konzepte: die Darstellungen einer bestimmten Zeichenfolge im Python-Quellcode und den regulären Ausdruck, den diese Zeichenfolge darstellt.
In der Tat ist es hilfreich, sich diese als zwei verschiedene Programmiersprachen mit jeweils eigener Syntax vorzustellen. Die Python-Sprache verfügt über Quellcode, der unter anderem Zeichenfolgen mit bestimmten Inhalten erstellt und das reguläre Ausdruckssystem aufruft. Das System mit regulären Ausdrücken verfügt über Quellcode, der sich in Zeichenfolgenobjekten befindet und mit Zeichenfolgen übereinstimmt. Beide Sprachen verwenden Backslash als Escape-Zeichen.
Verstehen Sie zunächst, dass eine Zeichenfolge eine Folge von Zeichen ist (dh Bytes oder Unicode-Codepunkte; die Unterscheidung spielt hier keine große Rolle). Es gibt viele Möglichkeiten, eine Zeichenfolge im Python-Quellcode darzustellen. Eine rohe Zeichenfolge ist einfach eine dieser Darstellungen. Wenn zwei Darstellungen zu derselben Zeichenfolge führen, erzeugen sie ein gleichwertiges Verhalten.
Stellen Sie sich eine 2-stellige Zeichenfolge vor, die aus dem Backslash- Zeichen gefolgt vom n- Zeichen besteht. Wenn Sie wissen, dass der Zeichenwert für Backslash 92 und für n 110 ist, generiert dieser Ausdruck unsere Zeichenfolge:
s = chr(92)+chr(110) print len(s), s 2 \n
Die herkömmliche Python-String-Notation
"\n"
generiert diesen String nicht. Stattdessen wird eine einstellige Zeichenfolge mit einem Zeilenumbruchzeichen generiert. Die Python-Dokumente 2.4.1. String-Literale sagen: "Das Backslash-Zeichen (\) wird verwendet, um Zeichen zu maskieren, die ansonsten eine besondere Bedeutung haben, z. B. Zeilenumbruch, Backslash selbst oder Anführungszeichen."s = "\n" print len(s), s 1
(Beachten Sie, dass die neue Zeile in diesem Beispiel nicht sichtbar ist. Wenn Sie jedoch genau hinschauen, wird nach der "1" eine leere Zeile angezeigt.)
Um unsere zweistellige Zeichenfolge zu erhalten, müssen wir ein anderes Backslash- Zeichen verwenden, um der besonderen Bedeutung des ursprünglichen Backslash- Zeichens zu entgehen :
s = "\\n" print len(s), s 2 \n
Was ist, wenn Sie Zeichenfolgen darstellen möchten, die viele Backslash- Zeichen enthalten? Python-Dokumente 2.4.1. String-Literale fahren fort: "String-Literalen kann optional ein Buchstabe 'r' oder 'R' vorangestellt werden. Solche Strings werden als Raw-Strings bezeichnet und verwenden unterschiedliche Regeln für die Interpretation von Backslash-Escape-Sequenzen." Hier ist unsere zweistellige Zeichenfolge mit roher Zeichenfolgendarstellung:
s = r"\n" print len(s), s 2 \n
Wir haben also drei verschiedene Zeichenfolgendarstellungen, die alle dieselbe Zeichenfolge oder Zeichenfolge enthalten:
print chr(92)+chr(110) == "\\n" == r"\n" True
Wenden wir uns nun den regulären Ausdrücken zu. Die Python-Dokumente, 7.2.
re
- Bei Operationen mit regulären Ausdrücken heißt es: "Reguläre Ausdrücke verwenden das Backslash-Zeichen ('\'), um Sonderformen anzugeben oder die Verwendung von Sonderzeichen zu ermöglichen, ohne ihre besondere Bedeutung aufzurufen. Dies kollidiert mit Pythons Verwendung desselben Zeichens für denselben Zweck in String-Literale ... "Wenn Sie ein Python-Objekt mit regulären Ausdrücken möchten, das einem Zeilenumbruchzeichen entspricht, benötigen Sie eine 2-stellige Zeichenfolge, die aus dem Backslash- Zeichen gefolgt vom n- Zeichen besteht. Die folgenden Codezeilen setzen prog auf ein Objekt mit regulären Ausdrücken, das ein Zeilenumbruchzeichen erkennt:
prog = re.compile(chr(92)+chr(110)) prog = re.compile("\\n") prog = re.compile(r"\n")
Warum also "werden Muster normalerweise in Python-Code unter Verwendung dieser rohen String-Notation ausgedrückt." ? Weil reguläre Ausdrücke häufig statische Zeichenfolgen sind, die bequem als Zeichenfolgenliterale dargestellt werden. Aus den verschiedenen verfügbaren Zeichenfolgenliteralnotationen sind Rohzeichenfolgen eine bequeme Wahl, wenn der reguläre Ausdruck ein Backslash- Zeichen enthält.
Fragen
F : Was ist mit dem Ausdruck
re.compile(r"\s\tWord")
? A : Es ist einfacher zu verstehen, wenn Sie die Zeichenfolge von der Zusammenstellung regulärer Ausdrücke trennen und separat verstehen.s = r"\s\tWord" prog = re.compile(s)
Die Zeichenfolge
s
enthält acht Zeichen: einen Backslash , ein s , einen Backslash , ein t und dann vier ZeichenWord
.F : Was passiert mit den Tabulator- und Leerzeichen? A : Auf der Python-Sprachebene hat die Zeichenfolge
s
keine Tabulator- und Leerzeichen . Es beginnt mit vier Zeichen: Backslash , s , Backslash , t . Das System für reguläre Ausdrücke behandelt diese Zeichenfolge unterdessen als Quellcode in der Sprache für reguläre Ausdrücke. Dabei bedeutet dies "Übereinstimmung mit einer Zeichenfolge, die aus einem Leerzeichen, einem Tabulatorzeichen und den vier Zeichen bestehtWord
.F : Wie passen Sie zu diesen, wenn dies als Backlash-s und Backslash-t behandelt wird? A : Vielleicht ist die Frage klarer, wenn die Wörter "Sie" und "das" spezifischer gemacht werden: Wie passt das System der regulären Ausdrücke zu den Ausdrücken "Backlash-s" und "Backslash-t"? Als 'beliebiges Leerzeichen' und als ' Tabulatorzeichen '.
F : Oder was ist, wenn Sie die 3-stellige Zeichenfolge Backslash-n-Newline haben? A : In der Python-Sprache kann die 3-stellige Zeichenfolge Backslash-n-Newline als herkömmliche Zeichenfolge
"\\n\n"
oder als rohe plus herkömmliche Zeichenfolger"\n" "\n"
oder auf andere Weise dargestellt werden. Das System für reguläre Ausdrücke entspricht dem Backslash-n-Newline mit drei Zeichenfolgen, wenn zwei aufeinanderfolgende Zeilenumbrüche gefunden werden .NB Alle Beispiele und Dokumentverweise beziehen sich auf Python 2.7.
Update : Eingeschlossene Klarstellungen aus den Antworten von @Vladislav Zorov und @ m.buettner sowie aus der Folgefrage von @Aerovistae.
quelle
s
in der Zeichenfolge enden und\t
zu einem Tabulatorzeichen werden. Jetzt werden nur noch zwei Zeichen an die Regex-Engine übergeben. Während die Engine möglicherweise noch mit einem Tabulatorzeichen übereinstimmen kann, versucht sie nun, ein vorangestelltes Zeichen zu findens
.ord(92)
wird nur ein erhöhenTypeError
, weil92
es kein String ist. Sie meinten wahrscheinlichchr(92)
(oder vielleichtunichr(92)
)?Die meisten dieser Fragen enthalten viele Wörter, und möglicherweise ist es schwierig, die Antwort auf Ihre spezifische Frage zu finden.
Wenn Sie eine reguläre Zeichenfolge verwenden und ein Muster wie "\ t" an den RegEx-Parser übergeben, übersetzt Python dieses Literal in einen Puffer mit dem darin enthaltenen Tab-Byte (0x09).
Wenn Sie eine unformatierte Zeichenfolge verwenden und ein Muster wie r "\ t" an den RegEx-Parser übergeben, führt Python keine Interpretation durch und erstellt einen Puffer mit zwei Bytes: '\' und 't'. (0x5c, 0x74).
Der RegEx-Parser weiß, was mit der Sequenz '\ t' zu tun ist - er vergleicht diese mit einer Registerkarte. Es weiß auch, was mit dem Zeichen 0x09 zu tun ist - das entspricht auch einer Registerkarte. Die Ergebnisse sind größtenteils nicht zu unterscheiden.
Der Schlüssel zum Verständnis des Geschehens liegt also darin, zu erkennen, dass hier zwei Parser verwendet werden. Der erste ist der Python-Parser, der Ihr String-Literal (oder Raw-String-Literal) in eine Folge von Bytes übersetzt. Der zweite ist Pythons Parser für reguläre Ausdrücke und konvertiert eine Folge von Bytes in einen kompilierten regulären Ausdruck.
quelle
Das Problem bei der Verwendung einer normalen Zeichenfolge zum Schreiben von regulären Ausdrücken, die a enthalten,
\
besteht darin, dass Sie am Ende\\
für jede schreiben müssen\
. Also die String-Literale"stuff\\things"
undr"stuff\things"
produzieren den gleichen String. Dies ist besonders nützlich, wenn Sie einen regulären Ausdruck schreiben möchten, der mit Backslashes übereinstimmt.Mit normalen Strings, einen regulären Ausdruck, der Zeichenfolge entspricht
\
wäre"\\\\"
!Warum? Weil wir
\
zweimal entkommen müssen : einmal für die Syntax des regulären Ausdrucks und einmal für die String-Syntax.Sie können dreifache Anführungszeichen verwenden, um Zeilenumbrüche wie folgt einzuschließen:
r'''stuff\ things'''
Beachten Sie, dass Python normalerweise
\
-newline als Zeilenfortsetzung behandelt , dies ist jedoch bei rohen Zeichenfolgen nicht der Fall. Beachten Sie auch, dass Backslashes immer noch Anführungszeichen in rohen Zeichenfolgen entgehen, aber in sich selbst verbleiben. Das rohe String-Literalr"\""
erzeugt also den String\"
. Dies bedeutet, dass Sie ein Raw-String-Literal nicht mit einem Backslash beenden können.Siehe den lexikalische Analyse Abschnitt der Python - Dokumentation für weitere Informationen.
quelle
r'''something<enter>onnewline'''
.<enter>
bedeutet, drücken Sie die Eingabetaste. Nicht gerade hübsch, also können Sie hier wahrscheinlich die Verkettung von Zeichenfolgen verwenden?r"stuff\"
ein Fehler vor.re.match(r'1\n2', string)
bedeutetre.match('1\\n2', string)
, wird also\n
nicht von Python interpretiert, sondern vom Regex-Parser - es liefert tatsächlich das gleiche Ergebnis wie einfach,re.match('1\n2', string)
da der Regex-Parser nicht entflohene Zeilenumbruchzeichen von Python gut verarbeitet (zumindest in meinen Python 3-Tests)Sie scheinen mit der Idee zu kämpfen, dass ein RegEx nicht Teil von Python ist, sondern eine andere Programmiersprache mit einem eigenen Parser und Compiler. Raw - Strings Hilfe erhalten Sie die „Quellcode“ einen RegEx sicher zum RegEx - Parser, die Zeichenfolge wird dann assign Bedeutung wie
\d
,\w
,\n
usw ...Das Problem besteht darin, dass Python und RegExps
\
als Escape-Zeichen verwendet werden, was übrigens ein Zufall ist. Es gibt Sprachen mit anderen Escape-Zeichen (wie "` n "für eine neue Zeile, aber selbst dort müssen Sie" \ n "verwenden. in RegExps). Der Vorteil ist, dass Sie in diesen Sprachen nicht zwischen rohen und nicht rohen Zeichenfolgen unterscheiden müssen. Beide versuchen nicht, den Text zu konvertieren und zu schlachten, da sie auf unterschiedliche Escape-Sequenzen reagieren.quelle
Der entsprechende Abschnitt des Python-Handbuchs ("String- und Byte-Literale") enthält eine klare Erklärung der rohen String-Literale:
quelle
\n
ist eine Escape-Sequenz in Python\w
ist eine spezielle Sequenz in (Python) RegexSie sehen aus, als wären sie in derselben Familie, aber sie sind es nicht. Die Raw-String-Notation wirkt sich auf Escape-Sequenzen aus, nicht jedoch auf Regex-Spezialsequenzen.
Weitere Informationen zu Escape Sequences finden Sie unter "\ newline" unter https://docs.python.org/3/reference/lexical_analysis.html
Weitere Informationen zu speziellen Sequenzen: Suchen Sie nach "\ number" https://docs.python.org/3/library/re.html
quelle
Die Rohzeichenfolge wirkt sich nicht auf spezielle Sequenzen in Python-Regex wie \ w, \ d aus. Es betrifft nur Escape-Sequenzen wie \ n. Die meiste Zeit spielt es also keine Rolle, ob wir r vorne schreiben oder nicht.
Ich denke, das ist die Antwort, nach der die meisten Anfänger suchen.
quelle