String splitten - aber nicht immer

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
finswimmer77
User
Beiträge: 13
Registriert: Freitag 14. Dezember 2012, 22:07

Hallo,

gegeben sei folgender Beispielstring:

row = "a,b,c[d,e],f"

Ich möchte diesen String nun an jedem Komma splitten, außer das Komma erscheint innerhalb der eckigen Klammern. Gibt's da ne Möglichkeit?

fin swimmer
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

regex.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
finswimmer77
User
Beiträge: 13
Registriert: Freitag 14. Dezember 2012, 22:07

darktrym hat geschrieben:regex.
Das hab ich befürchtet. Mit regex steh ich seit eh und je auf dem Kriegsfuß. Hättest du einen Codeschnipsel für mich?

Danke

fin swimmer
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Mit dem re-Module könnte eine Lösung so aussehen:

Code: Alles auswählen

import re

def limited_split(s):
    desired = ''.join(re.split(r'\[.*\]', s))
    return desired.split(',')

Code: Alles auswählen

>>> limited_split('a,b,c[d,e],f')
>>> ['a', 'b', 'c', 'f']
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
finswimmer77
User
Beiträge: 13
Registriert: Freitag 14. Dezember 2012, 22:07

Danke für die Antwort.

Das re-Modul wird vermutlich die Lösung liefern. So ganz erhalte ich mit deinem Beispiel mein Ziel aber noch nicht. Ziel sollte sein

Code: Alles auswählen

['a', 'b', 'c[d,e]', 'f']
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@finswimmer77
Dann musst Du eben die regex '\[.*\]' dahingehend ändern... :wink:

Ich weiß ja nicht, was Du vorhast, aber das ganze riecht sehr eigenartig... :wink:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@mutetella: Für was man da ein extra split braucht ist mir nicht klar

Code: Alles auswählen

values = re.findall(r'(?:[^,\[\]]|\[.*?\])+', row)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Sirius3 hat geschrieben:Für was man da ein extra split braucht ist mir nicht klar
Du musst eben noch viel lernen... :mrgreen:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
finswimmer77
User
Beiträge: 13
Registriert: Freitag 14. Dezember 2012, 22:07

Sirius3 hat geschrieben:@mutetella: Für was man da ein extra split braucht ist mir nicht klar

Code: Alles auswählen

values = re.findall(r'(?:[^,\[\]]|\[.*?\])+', row)
Vielen Dank! Das scheint genau das zu machen, was ich möchte. Jetzt werd ich nur wieder ne ewigkeit brauchen, zu verstehen was der regex eigentlich macht.

fin swimmer
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

finswimmer77 hat geschrieben: Vielen Dank! Das scheint genau das zu machen, was ich möchte. Jetzt werd ich nur wieder ne ewigkeit brauchen, zu verstehen was der regex eigentlich macht.
Na ja, die Alternative wäre, das selbst per Hand zu machen, in dem du den String Zeichen für Zeichen durchgehst, und dir merkst, ob du dich gerade in einer eckigen Klammer befindest, oder nicht. Das, was man da schreibtt, ist dann vom Effekt her eine (schlechtere) Implementation eines kleinen Subsets dessen, was mit regulären Ausdrücken möglich ist. Das macht man üblicherweise nicht, weil reguläre Ausdrücke zwar vielleicht etwas kompliziert zu schreiben, sonst aber für den Zweck überlegen sind.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ein Ansatz in die Richtung State-Machine habe ich einst implementiert: https://github.com/Lysander/snippets/bl ... nslator.py

@nezzcarth: Pauschal kann man das nicht sagen - ist die Struktur tatsächlich rekursiv aufgebaut, kommst Du mit RegExps nicht weit... für eine feste Ausnahme wie in diesem Falle hast Du natürlich recht.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@nezzcarth: Es gäbe noch die Möglichkeit eine Parserbibliothek zu verwenden. Ist auch übertrieben, aber vielleicht lesbarer.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Sirius3 hat geschrieben:

Code: Alles auswählen

values = re.findall(r'(?:[^,\[\]]|\[.*?\])+', row)
Jetzt muss ich mir nur noch erschließen, wie die non-capturing Group dazu beiträgt den kompletten String 'c[d,e]' zu liefern. Das erste Muster im regulären Ausdruck ist klar, das zweite auch - aber wodurch liefert mir der Gesamtausdruck das Ergebnis das er liefert? *grübel*
BlackJack

@/me: Durch das '+' und das nichts in der Gruppe auf Kommas ausserhalb von eckigen Klammern matcht.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:@/me: Durch das '+' und das nichts in der Gruppe auf Kommas ausserhalb von eckigen Klammern matcht.
Ach klar. Das '+' hatte ich nicht wirklich wahrgenommen. Danke.
Antworten