Warum produzieren diese beiden Python-Regexe unterschiedliche Ergebnisse?

>>> re.match(r'"([^"]|(\\\"))*"', r'"I do not know what \"A\" is"').group(0) '"I do not know what \\"' >>> re.match(r'"((\\\")|[^"])*"', r'"I do not know what \"A\" is"').group(0) '"I do not know what \\"A\\" is"' 

Diese beiden Regexen sollen nach zitierten Strings suchen, mit Escaped-Zitat-Sequenzen. Der Unterschied, wenn ich nicht etwas fehlt, ist die Reihenfolge der Disjunktion in den Klammern.

Warum nehmen sie nicht beide die ganze Saite an?

3 Solutions collect form web for “Warum produzieren diese beiden Python-Regexe unterschiedliche Ergebnisse?”

Die Reihenfolge in Wechselgruppen ist wichtig.

In der ersten Regex wird die [^"] Alternative zuerst für jedes Zeichen versucht, es passt jedes einzelne Zeichen bis zu (und einschließlich) dem ersten \ . Beim nächsten Zeichen ( " ) fällt diese Alternative ( [^"] ) und die Andere ( \\\" ) versucht. Letzteres scheitert auch, da "A nicht mit \\\" übereinstimmt. Dies stoppt den Quantifizierer * von weiteren Spielen.

In der zweiten Regex ist die \\\" Alternative (Klammer ist redundant) zuerst für jedes Zeichen versucht und scheitert, so dass die zweite Alternative ( [^"] ) übereinstimmt. Aber bei den ersten \ die ersten alternativen Streichhölzer geht der Lookup-Pointer vorbei an \" A und der Lookup geht weiter.

Als eine allgemeine Faustregel, legen Sie den schmalsten Ausdruck im Wechsel zuerst.

Was du sagst, ist wahr, die Ordnung ist anders. Und noch etwas anderes ist anders.
Die erste "([^"]|(\\\"))*" wird mit einer Flucht übereinstimmen
Match "asdf\" sde ", während die andere nicht.

Auch wenn du mit Escape-Zitat umgehen musst, musst du auch Escapes behandeln. Also ist keines gültig.

Hier sind zwei Arten von Standard-Möglichkeiten, dies zu tun.
Beide behandeln die Flucht.
Sie können dies auch auf einfache Anführungszeichen erweitern.
Benutze den Dot-All-Modifikator (?s) wenn du Newlines überspannen möchtest.

Methode 1. – Wechsel

"(?:\\.|[^"\\]+)*"

  " (?: \\ . # Escape anything | # or, [^"\\]+ # Not escape not quote )* " 

Methode 2. – abgerollte Schleife

"[^"\\]*(?:\\.[^"\\]*)*"

  " [^"\\]* # Optional not escape not quote (?: \\ . # Escape anything [^"\\]* # Optional not escape not quote )* " 

Beide machen das gleiche. Methode 2 ist drei bis fünf Mal schneller als Methode 1.

Die Regex r'(A|B)' wird zuerst versuchen, mit A übereinzustimmen, und nur wenn das scheitert, wird es versuchen, B ( docs )

So wird die Regex ([^"]|(\\\") zuerst versuchen, mit einem Nicht-Anführungszeichen übereinzustimmen, und wenn das scheitert, wird es versuchen, mit einem Escaped-Anführungszeichen übereinzustimmen.

Wenn also der Regex \"A\" erreicht, stimmt der erste Teil Teil mit dem \ (es handelt sich nicht um ein Zitat, aber dann kein Teil passt, so dass das Spiel endet. Der Backslash wird von der [^"] verschoben, also der zweite Die Hälfte des Ausdrucks wird nie benutzt.

(\\ ") | [^"]), wenn es \"A\" wird zuerst versuchen, die \" (es funktioniert) dann wird es versuchen, A (es entspricht [^"] und So geht das Spiel weiter.

  • Regex to Match "Chinesisch + Zahl" Muster in Python
  • Python reg ex mit fehlenden kommas
  • Regex, um eine Erfassungsgruppe ein oder mehrere Male anzupassen
  • Variable-length-Lookbehind-Assertion-Alternativen für reguläre Ausdrücke
  • Regex für die Suche und bekommen die src eines Bildes
  • Rückkehr von einzigartigen Streichhölzern mit Regex in Python
  • Wie kann ich optional mit einem zusätzlichen Teilstring mit Python regulären Ausdrücken übereinstimmen?
  • Python regelmäßiger Ausdruck, zieht alle Briefe aus
  • Regex ersetzt Text zwischen Trennzeichen in Python
  • Wie man benutzerdefinierte Tags mit nltk.Regexp.parser ()
  • Reguläre Ausdrücke: Suche in der Liste
  • Python ist die beste Programmiersprache der Welt.