Ich möchte eine Eingabezeichenfolge analysieren und bestimmen, ob sie eine Folge von Zeichen enthält, die von doppelten Anführungszeichen umgeben sind ("
). Die Zeichenfolge selbst darf keine weiteren doppelten Anführungszeichen enthalten, es sei denn, sie werden durch einen umgekehrten Schrägstrich wie folgt geschützt: \"
.Wie wird nach einem Zeichenfolgenliteral gesucht, das Escapezeichen erlaubt?
Um die Dinge komplizierter zu machen, können die Backslashes selbst gemieden werden: \\
. Ein doppeltes Anführungszeichen, dem zwei (oder eine gerade Anzahl) Backslashes vorangestellt sind (\\"
), ist daher nicht maskiert. Und um es noch schlimmer zu machen, sind einzelne nicht entkommene Backslashes (d. H. Weder gefolgt von "
noch \
) erlaubt.
Ich versuche, das mit Pythons re
Modul zu lösen. Die module documentation erzählt uns von dem Rohr Operator A|B
:
Da die Zielzeichenfolge abgetastet wird, durch
'|'
getrennt REs versucht werden von links nach rechts. Wenn ein Muster vollständig übereinstimmt, wird dieser Zweig akzeptiert. Dies bedeutet, dassA
, wennB
nicht mehr getestet wird, auch wenn es eine längere Gesamtübereinstimmung ergeben würde. Mit anderen Worten, der Operator'|'
ist niemals gierig.
jedoch dies nicht funktioniert, wie ich erwartete:
>>> import re
>>> re.match(r'"(\\[\\"]|[^"])*"', r'"a\"')
<_sre.SRE_Match object; span=(0, 4), match='"a\\"'>
Die Idee dieser regex ist, zuerst Prüfung für ein Escape-Zeichen (\\
oder \"
) und nur, wenn diese nicht gefunden wird, überprüfen Sie für jedes Zeichen, das nicht "
ist (aber es könnte ein einzelnes sein \
). Dies kann beliebig oft geschehen und muss von Literalen "
Zeichen umgeben sein.
Ich würde erwarten, dass die Zeichenfolge "a\"
überhaupt nicht übereinstimmen, aber anscheinend tut es. Ich würde erwarten, \"
, um die A
Teil übereinstimmen und die B
Teil nicht getestet werden, aber anscheinend ist es.
Ich weiß nicht wirklich, wie das Backtracking in diesem Fall funktioniert, aber gibt es eine Möglichkeit, es zu vermeiden?
Ich denke, es würde funktionieren, wenn ich zuerst für das ursprüngliche "
Zeichen prüfen (und es von der Eingabe entfernen) in einem separaten Schritt. Ich kann dann den folgenden regulären Ausdruck verwendet, den Inhalt der Zeichenfolge zu erhalten:
>>> re.match(r'(\\[\\"]|[^"])*', r'a\"')
<_sre.SRE_Match object; span=(0, 3), match='a\\"'>
Dies würde das entwichene Zitat enthält. Da es kein abschließendes Zitat geben würde, würde ich wissen, dass die angegebene Zeichenfolge insgesamt nicht übereinstimmt.
Muss ich es so machen oder ist es möglich, dies mit einem einzigen regulären Ausdruck und ohne zusätzliche manuelle Überprüfung zu lösen?
In meiner realen Anwendung ist die "
-geschlossene Zeichenfolge nur ein Teil eines größeren Musters, also denke ich, es wäre einfacher, alles auf einmal in einem einzigen regulären Ausdruck zu tun.
fand ich ähnliche Fragen, aber die nicht berücksichtigen, dass ein einzelner nicht-Flucht Backslash Teil der Zeichenfolge sein kann: regex to parse string with escaped characters, Parsing for escape characters with a regular expression.
Siehe: '" (?: [^ \\ "] | \\.) *" '->' "[^" \\] * (?: \\. [^ "\\] *) * "' –
Danke, das funktioniert super! Was meinst du mit dem Pfeil? Ist eine der Alternativen besser als die andere? Sind sie genau gleichwertig? – Matthias
Ja, es gibt einen Unterschied. Okay, lassen Sie mich das als Antwort betrachten, denn das funktioniert für Sie. –