Regulärer Ausdruck, um eine kommagetrennte Liste von Schlüssel = Wert zu finden, wobei Wert Kommas enthalten kann

8

Ich habe einen naiven "Parser", der einfach so etwas macht wie:
[x.split('=') for x in mystring.split(',')]

Allerdings kann mystring etwas wie% code%% / / sein

Offensichtlich,
Der naive Splitter wird es einfach nicht tun. Ich beschränke mich auf Python 2.6 Standardbibliothek dafür So kann zum Beispiel pyparsing nicht verwendet werden.

Erwartete Ausgabe ist
'foo=bar,breakfast=spam,eggs'

Ich versuche, dies mit Regex zu tun, habe aber folgende Probleme:

Mein erster Versuch
[('foo', 'bar'), ('breakfast', 'spam,eggs')]
Gab mir
r'([a-z_]+)=(.+),?'

Offensichtlich,
Wenn [('foo', 'bar,breakfast=spam,eggs')] nicht gierig gemacht wird, wird das Problem nicht gelöst.

Also,
Ich schätze, ich muss irgendwie das letzte Komma (oder .+ ) zwingend machen.
Doing nur das funktioniert nicht wirklich,
$
Wie damit wird das Zeug hinter dem Komma in einem Wert, der eins enthält, weggelassen z.B. r'([a-z_]+)=(.+?)(?:,|$)'

Ich denke, ich muss eine Art Look-Behind (?) -Operation verwenden.
Die Frage (n)
1. Welche verwende ich? oder
2. Wie mache ich das / das?

Bearbeiten :

Basierend auf daramarak 's Antwort unten,
Am Ende habe ich fast dasselbe getan wie abarnert später vorgeschlagen in einer etwas ausführlicheren Form;

%Vor%

EDIT 2:

Nur um meine Neugier zu befriedigen, ist das eigentlich möglich mit reinen regulären Ausdrücken? Dh, dass [('foo', 'bar'), ('breakfast', 'spam')] eine Liste von 2-Tupeln zurückgeben würde?

    
Kimvais 01.02.2013, 07:41
quelle

5 Antworten

8

Nur zum Vergleich, hier ist eine Regex, die das Problem ebenfalls zu lösen scheint:

%Vor%

Der Trick hier, um einzuschränken, was Sie in Ihrer zweiten Gruppe erfassen. .+ schluckt das = -Zeichen, welches das Zeichen ist, mit dem wir Schlüssel von Werten unterscheiden können. Die vollständige Regex ist nicht auf Rückverfolgung angewiesen (daher sollte sie mit etwas wie re2 kompatibel sein, wenn dies der Fall ist) wünschenswert) und kann an abarnerts Beispielen arbeiten.

Verwendung wie folgt:

%Vor%

Was zurückgibt:

%Vor%     
ig0774 01.02.2013, 10:55
quelle
4

Die Antwort von daramarak funktioniert entweder fast oder funktioniert so wie sie ist; Es ist schwer zu erkennen, wie die Beispielausgabe formatiert ist und wie die Schritte vage beschrieben werden. Aber wenn es die Fast-Fast-Version ist, ist es einfach zu beheben.

Setzen Sie es in den Code:

%Vor%

Die erste Zeile ist (glaube ich) die Antwort von daramarak. Die erste Zeile gibt dir selbst Paare von (value_i, key_i+1) anstelle von (key_i, value_i) . Die zweite Zeile ist die naheliegendste Lösung dafür. Mit mehr Zwischenschritten und etwas Ausgabe, um zu sehen, wie es funktioniert:

%Vor%     
abarnert 01.02.2013 08:14
quelle
1

Könnte ich vorschlagen, dass Sie die Split-Operationen wie zuvor verwenden? Aber spalte zuerst am Gleichen und dann am ganz rechts stehenden Komma, um eine einzige Liste von linken und rechten Strings zu erstellen.

%Vor%

wird zuerst aufgeteilt

%Vor%

Wenn Sie das Komma ganz rechts aufteilen, erhalten Sie:

%Vor%

Dann sammelst du die Paare einfach so:

%Vor%     
daramarak 01.02.2013 07:53
quelle
0

Kannst du es versuchen, es hat für mich funktioniert:

%Vor%

Sie erhalten ein Ergebnis wie:

%Vor%

Dann kannst du einfach über die Liste gehen und tun, was du willst.

    
iblazevic 01.02.2013 08:12
quelle
0

Wenn der Name des Schlüssels niemals , enthält, können Sie ihn in , teilen, wenn die nächste Sequenz ohne , und = mit = abgeschlossen wird.

%Vor%

(Dies ist das gleiche wie meine ursprüngliche Lösung. Ich erwarte, dass re.split verwendet wird, anstatt re.findall oder str.split ).

Die vollständige Lösung kann in einem Liner erfolgen:

%Vor%     
nhahtdh 01.02.2013 13:23
quelle

Tags und Links