sub - python regex replace all




Was genau ist ein "reiner Strang-Regex" und wie können Sie ihn verwenden? (4)

Aus der Python-Dokumentation zu regex zum '\' Zeichen:

Die Lösung besteht darin, die Python-Schreibweise für reguläre Ausdrücke zu verwenden. Backslashes werden in einem String-Literal mit 'r' nicht besonders behandelt. So ist r"\n" eine aus zwei Zeichen bestehende Zeichenfolge, die '\' und 'n' , während "\n" eine aus nur einem Zeichen bestehende Zeichenfolge ist, die eine neue Zeile enthält. Normalerweise werden Muster in Python-Code mit dieser rohen String-Notation ausgedrückt.

Was ist diese rohe Stringnotation? Wenn Sie ein Roh-String-Format verwenden, bedeutet dies, dass "*" als Literalzeichen und nicht als Null-Indikator verwendet wird. Das kann offensichtlich nicht richtig sein, sonst würde Regex seine Macht völlig verlieren. Wenn es sich jedoch um einen reinen String handelt, wie erkennt er Zeilenumbrüche, wenn "\n" buchstäblich ein Backslash und ein "n" ?

Ich folge nicht

Bearbeiten für Kopfgeld:

Ich versuche zu verstehen, wie ein reiner Regex für Rohstrings mit Zeilenumbrüchen, Registerkarten und Zeichensätzen übereinstimmt, z. B. \w für Wörter oder \d für Ziffern oder alles, was nicht, wenn Rohstringmuster Backslashes nicht als etwas mehr als gewöhnliche Zeichen erkennen. Ich könnte einige gute Beispiele gebrauchen.


Das Problem bei der Verwendung einer normalen Zeichenfolge zum Schreiben von regulären Ausdrücken, die ein \ enthalten, besteht darin, dass Sie \\ für jeden \ schreiben müssen. Die String-Literale "stuff\\things" und r"stuff\things" erzeugen also dieselbe Zeichenfolge. Dies ist besonders nützlich, wenn Sie einen regulären Ausdruck schreiben möchten, der mit umgekehrten Schrägstrichen übereinstimmt.

Bei Verwendung normaler Zeichenfolgen wäre ein regulärer Ausdruck, der mit der Zeichenfolge \ "\\\\" , "\\\\" .

Warum? Denn \ zweimal \ entkommen: einmal für die Syntax für reguläre Ausdrücke und einmal für die Zeichenfolgensyntax.

Sie können dreifache Anführungszeichen verwenden, um Zeilenumbrüche wie folgt aufzunehmen:

r'''stuff\
things'''

Beachten Sie, dass Python \ -newline normalerweise als Zeilenfortsetzung behandelt. Dies ist jedoch bei rohen Zeichenfolgen nicht der Fall. Beachten Sie auch, dass Backslashes in rohen Zeichenfolgen immer noch Anführungszeichen bleiben, aber in sich selbst bleiben. Das Roh-Stringliteral r"\"" erzeugt also den String \" . Das bedeutet, dass Sie ein Roh-String-Literal nicht mit einem Backslash beenden können.

Weitere Informationen finden Sie im Abschnitt zur lexikalischen Analyse der Python-Dokumentation .


Der entsprechende Python-Handbuchabschnitt ("String- und Bytes-Literale") enthält eine klare Erklärung der Roh-String-Literale:

Sowohl String- als auch Byte-Literalen können optional mit einem Buchstaben 'r' oder 'R' vorangestellt werden. Solche Zeichenfolgen werden als unformatierte Zeichenfolgen bezeichnet und behandeln Backslashes als wörtliche Zeichen. In String-Literalen werden daher die Zeichen '\ U' und '\ u' in Roh-Strings nicht speziell behandelt. Da sich die unbehandelten Unicode-Literale von Python 2.x anders als die von Python 3.x verhalten, wird die 'ur'-Syntax nicht unterstützt.

Neu in Version 3.3: Das 'rb' Präfix der rohen Bytes Literale wurde als Synonym für 'br' hinzugefügt.

Neu in Version 3.3: Die Unterstützung für das Unicode-Legacy-Literal (u'value) wurde wieder eingeführt, um die Pflege von dualen Python-2.x- und 3.x-Codebasen zu vereinfachen. Weitere Informationen finden Sie in PEP 414.

In Strings mit drei Anführungszeichen sind nicht umschriebene Zeilenumbrüche und Anführungszeichen zulässig (und werden beibehalten), mit der Ausnahme, dass drei nicht umschriebene Anführungszeichen in einer Zeile den String beenden. (Ein "Anführungszeichen" ist das Zeichen, das zum Öffnen der Zeichenfolge verwendet wird, dh entweder 'oder ".)

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

Notensequenz-Bedeutungshinweise

\ newline Backslash und Newline werden ignoriert
\ Backslash ()
Einzelnes Zitat (')
\ "Anführungszeichen (")
\ a ASCII Bell (BEL)
\ b ASCII-Rücktaste (BS)
\ f ASCII-Formfeed (FF)
\ n ASCII-Zeilenvorschub (LF)
ASCII-Wagenrücklauf (CR)
\ t Horizontale ASCII-Registerkarte (TAB) \ v Vertikale ASCII-Registerkarte (VT)
ooo Zeichen mit Oktalwert ooo (1,3)
\ xhh Zeichen mit Hexadezimalwert hh (2,3)

Escape-Sequenzen, die nur in String-Literalen erkannt werden, sind:

Escape-Sequenz Bedeutung Notes \ N {Name} Zeichen mit Namen in der Unicode-Datenbank (4) \ uxxxx Zeichen mit 16-Bit-Hex-Wert xxxx (5) \ Uxxxxxxxx Zeichen mit 32-Bit-Hex-Wert xxxxxxxx (6)

Anmerkungen:

  1. Wie in Standard C werden bis zu drei Oktalstellen akzeptiert.

  2. Im Gegensatz zu Standard C sind genau zwei Hex-Ziffern erforderlich.

  3. In einem Byte-Literal, einem Hexadezimal- und einem Oktal-Escapezeichen wird das Byte mit dem angegebenen Wert angegeben. In einem String-Literal kennzeichnen diese Escape-Zeichen ein Unicode-Zeichen mit dem angegebenen Wert.

  4. In Version 3.3 geändert: Unterstützung für Namensaliasnamen [1] wurde hinzugefügt.

  5. Mit dieser Escape-Sequenz können einzelne Codeeinheiten codiert werden, die Teile eines Ersatzpaares bilden. Es sind genau vier Hex-Ziffern erforderlich.

  6. Jedes Unicode-Zeichen kann auf diese Weise codiert werden. Zeichen außerhalb der Basic Multilingual Plane (BMP) werden jedoch mit einem Ersatzpaar codiert, wenn Python für die Verwendung von 16-Bit-Codeeinheiten (Standardeinstellung) kompiliert wird. Es sind genau acht Hex-Ziffern erforderlich.

Im Gegensatz zu Standard C bleiben alle nicht erkannten Escape-Sequenzen in der Zeichenfolge unverändert, dh der Backslash bleibt in der Zeichenfolge. (Dieses Verhalten ist beim Debuggen hilfreich: Wenn eine Escape-Sequenz falsch eingegeben wird, wird die resultierende Ausgabe leichter als fehlerhaft erkannt.) Außerdem ist zu beachten, dass die Escape-Sequenzen, die nur in String-Literalen erkannt werden, in die Kategorie der nicht erkannten Escape-Bytes fallen Literale.

Auch in einer unformatierten Zeichenfolge können Anführungszeichen mit einem Backslash umgangen werden, der Backslash bleibt jedoch in der Zeichenfolge. Beispielsweise ist r "\" "ein gültiges Zeichenfolgenliteral, das aus zwei Zeichen besteht: einem umgekehrten Schrägstrich und einem doppelten Anführungszeichen; r" \ "ist kein gültiges Zeichenfolgenliteral (selbst eine rohe Zeichenfolge kann nicht in einer ungeraden Anzahl von umgekehrten Schrägstrichen enden). Insbesondere kann eine rohe Zeichenfolge nicht mit einem einzelnen Backslash enden (da der Backslash das folgende Anführungszeichen durchlaufen würde.) Beachten Sie außerdem, dass ein einzelner Backslash, gefolgt von einer Zeile, als diese beiden Zeichen als Teil der Zeichenfolge interpretiert wird, nicht als Zeilenfortsetzung .


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 helfen Ihnen, den "Quellcode" eines RegEx sicher in den RegEx-Parser zu bringen, der dann Zeichenfolgen wie \d , \w , \n usw. eine Bedeutung zuweist.

Das Problem tritt auf, weil Python und RegExps als Escape-Zeichen verwendet werden, was übrigens ein Zufall ist - es gibt Sprachen mit anderen Escape-Zeichen (wie "n" für einen Zeilenumbruch, 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 umzuwandeln und ihn zu schlachten, da sie auf unterschiedliche Escape-Sequenzen reagieren.


Zarkonnens Antwort beantwortet Ihre Frage, aber nicht direkt. Lassen Sie mich versuchen, direkter zu sein, und schauen Sie, ob ich die Prämie von Zarkonnen holen kann.

Sie werden dies vielleicht leichter verstehen, wenn Sie die Begriffe "reiner Strang regex" und "rohe String-Muster" verwenden. Diese Ausdrücke vereinen zwei getrennte Konzepte: die Repräsentationen einer bestimmten Zeichenfolge im Python-Quellcode und den regulären Ausdruck, den diese Zeichenfolge darstellt.

Tatsächlich ist es hilfreich, diese als zwei verschiedene Programmiersprachen mit jeweils eigener Syntax zu betrachten. Die Python-Sprache enthält Quellcode, der unter anderem Zeichenfolgen mit bestimmten Inhalten erstellt und das System für reguläre Ausdrücke aufruft. Das System für reguläre Ausdrücke verfügt über Quellcode, der sich in String-Objekten befindet, und stimmt mit Strings überein. 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 Rolle). Es gibt viele Möglichkeiten, eine Zeichenfolge im Python-Quellcode darzustellen. Eine rohe Zeichenfolge ist einfach eine dieser Darstellungen. Wenn zwei Repräsentationen zu derselben Zeichenfolge führen, erzeugen sie ein gleichwertiges Verhalten.

Stellen Sie sich eine 2-stellige Zeichenfolge vor, bestehend aus dem Backslash- Zeichen gefolgt von dem n- Zeichen. 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-Zeichenfolgennotation "\n" generiert diese Zeichenfolge nicht. Stattdessen wird eine aus nur einem Zeichen bestehende Zeichenfolge mit einem Zeilenvorschubzeichen erstellt. Die Python-Dokumente 2.4.1. String-Literale sagen: "Das Backslash-Zeichen (\) wird verwendet, um Zeichen zu umgehen, die ansonsten eine besondere Bedeutung haben, wie z. B. Newline, Backslash selbst oder das Anführungszeichen."

s = "\n"
print len(s), s

1 
 

(Beachten Sie, dass der Zeilenumbruch in diesem Beispiel nicht sichtbar ist. Wenn Sie jedoch genau hinschauen, sehen Sie nach der "1" eine leere Zeile.)

Um unsere aus zwei Zeichen bestehende Zeichenfolge zu erhalten, müssen wir einen anderen umgekehrten Schrägstrich verwenden, um der besonderen Bedeutung des ursprünglichen umgekehrten Schrägstrichs 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: "Den String-Literalen kann optional ein Buchstabe" r "oder" R "vorangestellt werden; solche Zeichenfolgen werden als Roh-Strings bezeichnet und verwenden unterschiedliche Regeln zum Interpretieren von Backslash-Escape-Sequenzen." Hier ist unsere aus zwei Zeichen bestehende Zeichenfolge, die die Darstellung der Rohzeichenfolge verwendet:

s = r"\n"
print len(s), s

2 \n

Wir haben also drei verschiedene Zeichenfolgendarstellungen, die alle dieselbe Zeichenfolge oder Folge von Zeichen enthalten:

print chr(92)+chr(110) == "\\n" == r"\n"
True

Wenden wir uns nun regulären Ausdrücken zu. Die Python-Dokumente, 7.2. re regulären Ausdrücken heißt es: "Reguläre Ausdrücke verwenden den umgekehrten Schrägstrich ('\'), um Sonderformen anzuzeigen oder Sonderzeichen zu verwenden, ohne dass ihre spezielle Bedeutung aufgerufen wird. Dies kollidiert mit Pythons Verwendung desselben Zeichens für denselben Zweck in String-Literalen ... "

Wenn Sie ein Python-Objekt für reguläre Ausdrücke wünschen, das einem Zeilenumbruchzeichen entspricht, benötigen Sie eine aus zwei Zeichen bestehende Zeichenfolge, die aus dem umgekehrten Schrägstrich gefolgt von dem Zeichen n besteht . Die folgenden Codezeilen setzen prog auf ein reguläres Ausdrucksobjekt, das ein Zeilenvorschubzeichen erkennt:

prog = re.compile(chr(92)+chr(110))
prog = re.compile("\\n")
prog = re.compile(r"\n")

Warum ist es so, dass "Normalerweise Muster in Python-Code mit dieser rohen String-Notation ausgedrückt werden." ? Denn reguläre Ausdrücke sind häufig statische Zeichenfolgen, die bequem als Zeichenfolgenliterale dargestellt werden. Unter den verschiedenen verfügbaren String-Literalnotationen sind rohe Zeichenfolgen eine bequeme Wahl, wenn der reguläre Ausdruck ein Backslash- Zeichen enthält.

Fragen

F : Wie re.compile(r"\s\tWord") mit dem Ausdruck re.compile(r"\s\tWord") ? A : Es ist einfacher zu verstehen, indem Sie die Zeichenfolge von der Kompilierung regulärer Ausdrücke trennen und sie separat verstehen.

s = r"\s\tWord"
prog = re.compile(s)

Die Zeichenfolge s enthält acht Zeichen: einen umgekehrten Schrägstrich , ein s , einen umgekehrten Schrägstrich , ein t und dann vier Zeichen Word .

F : Was passiert mit den Tabulatoren und Leerzeichen? A : Auf der Python-Sprachebene hat die Zeichenfolge s kein Tabulatorzeichen und Leerzeichen . Es beginnt mit vier Zeichen: Backslash , s , Backslash , t . Das System für reguläre Ausdrücke behandelt diese Zeichenfolge jedoch als Quellcode in der Sprache für reguläre Ausdrücke, wobei es bedeutet "Übereinstimmung mit einer Zeichenfolge, die aus einem Leerzeichen, einem Tabulatorzeichen und den vier Zeichen Word .

F : Wie passt das zusammen, wenn das als Backlash-s und Backslash-t behandelt wird? A : Vielleicht ist die Frage klarer, wenn die Wörter "du" und "das" genauer definiert werden: Wie passt das reguläre Ausdruckssystem zu den Ausdrücken backlash-s und backslash-t? Als 'beliebiges Leerzeichen' und als ' Tabulatorzeichen '.

F : Oder was ist, wenn Sie die dreizeilige 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 unformatierte Zeichenfolge r"\n" "\n" oder auf andere Weise dargestellt werden . Das System für reguläre Ausdrücke stimmt mit der dreizeiligen Zeichenfolge backslash-n-newline überein, wenn es zwei aufeinanderfolgende Zeilenumbrüche findet .

Hinweis: Alle Beispiele und Dokumentverweise beziehen sich auf Python 2.7.

Update : Eingehobene Klarstellungen aus den Antworten von @Vladislav Zorov und @m.buettner sowie aus der Folgefrage von @Aerovistae.





rawstring