Regulärer Ausdruck: verschachtelte Klammer

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.
Jack Daniels
User
Beiträge: 30
Registriert: Freitag 1. Januar 2010, 11:38

Hallo,

ich habe einen regulären Ausdruck, der Klammern erkennt:

Code: Alles auswählen

r'\([^\)]+\)
Das funktioniert auch soweit, jetzt will ich jedoch auch verschachtelte Klammern finden, also aus

Code: Alles auswählen

"(...(...)...)"
nicht

Code: Alles auswählen

"(...(...)", "...)"
machen, sondern alles an einem Stück lassen.

Geht das irgendwie mit regulären Ausdrücken, oder muss ich dass umständlicher schreiben? Danke schonmal.

Jack Daniels
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Rekursion geht mit regulären Ausdrücken nicht, insofern musst du "dass umständlicher schreiben".
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Wenn Du die maximale Verschachtelungstiefe kennst, wäre das schon möglich. Wird je nach Tiefe aber entsprechend umständlich.
Übrigens: der Backslash in [] ist unnötig.

Code: Alles auswählen

Note that inside [] the special forms and special characters lose their meanings and only the syntaxes described here are valid.
For example, +, *, (, ), and so on are treated as literals inside [], and backreferences cannot be used inside [].
MfG
HWK
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

DasIch hat geschrieben:Rekursion geht mit regulären Ausdrücken nicht, insofern musst du "dass umständlicher schreiben".
Zumindest ist das in Pythons Implementierung von regulären Ausdrücken so ... leider.
Panke
User
Beiträge: 185
Registriert: Sonntag 18. März 2007, 19:26

snafu hat geschrieben:
DasIch hat geschrieben:Rekursion geht mit regulären Ausdrücken nicht, insofern musst du "dass umständlicher schreiben".
Zumindest ist das in Pythons Implementierung von regulären Ausdrücken so ... leider.
Das ist leider eine Eigenschaft von rationalen Sprachen. Das hat mit Python nichts zu tun. Wenn ein regulärer Ausdruck ausgeglichene Klammern beliebiger Tiefe erkennen kann, dann ist es per definitionem kein regulärer Ausdruck.
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Naja, selbst wenn es keine Regexp im ursprünglichen Sinne ist, wird hier zumindest gezeigt, was mit Ruby und Perl möglich ist.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Panke hat geschrieben:Das ist leider eine Eigenschaft von rationalen Sprachen.
Meinten Sie "reguläre Sprachen" :)

snafu: Auch wenn Perls Regexp turingvollständig sind, ists trotzdem die denkbar schmerzvollste Art und Weise zu programmieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6861
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Du meinst jetzt das Programmieren in Perl oder die speziell die Regexp-Grammatik in Perl?
Jack Daniels
User
Beiträge: 30
Registriert: Freitag 1. Januar 2010, 11:38

OK danke, dann werd ich das anders lösen. :)
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Das hilft Dir vielleicht dabei.
MfG
HWK
Jack Daniels
User
Beiträge: 30
Registriert: Freitag 1. Januar 2010, 11:38

Falls es jemand interessiert, ich habs jetzt so gemacht:

Code: Alles auswählen

def tok(exp):
    lev = 0
    lst = []
    tmp = ""
    for pos in range(len(exp)):
        alev = lev
        if exp[pos] == "(":
            lev += 1
        elif exp[pos] == ")":
            lev -= 1

        if (lev == 0 and alev == 1) and tmp != "":
            # Klammer geöffnet -> das, was davor stand hinzufügen
            tmp += exp[pos]
            lst.append(tmp)
            tmp = ""
        elif (lev == 1 and alev == 0) and tmp != "":
            # Klammer geschlossen -> die Klammer selbst hinzufügen
            lst.append(tmp)
            tmp = exp[pos]
        else:
            tmp += exp[pos]
    if tmp != "":
        lst.append(tmp)

    return lst
Das macht aus

Code: Alles auswählen

"...(...(...)...)..."

Code: Alles auswählen

["...", "(...(...)...)", "..."]
Funktioniert einwandfrei. Danke für die Hilfe.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Da gibt es natuerlich noch ein bisschen was zum verbessern ;)

Code: Alles auswählen

for pos in range(len(exp)):
zu

Code: Alles auswählen

for char in exp:
(und natuerlich alle `exp[pos]` zu `char`)

und

Code: Alles auswählen

if tmp != "":
zu

Code: Alles auswählen

if tmp:
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

wieso verwendet man eig. immer dieses hässliche if x != i-was und nicht if not x == i-was
the more they change the more they stay the same
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Code: Alles auswählen

def tok(exp):
    lev = 0
    lst = []
    tmp = ''
    for c in exp:
        if c == '(':
            lev += 1
            if lev == 1 and tmp:
                lst.append(tmp)
                tmp = '('
                continue
        elif c == ')':
            lev -= 1
            if lev == 0:
                lst.append(tmp + ')')
                tmp = ''
                continue
            if lev < 0:
                break
        tmp += c
    if lev:
        raise ValueError, 'Unbalanced parentheses'
    if tmp:
        lst.append(tmp)
    return lst
MfG
HWK
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dav1d hat geschrieben:wieso verwendet man eig. immer dieses hässliche if x != i-was und nicht if not x == i-was
Weil schneller zu schreiben und irgendwie auch klarer...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

jens hat geschrieben:
Dav1d hat geschrieben:wieso verwendet man eig. immer dieses hässliche if x != i-was und nicht if not x == i-was
Weil schneller zu schreiben und irgendwie auch klarer...
Du findest ein einzelnes Zeichen klarer als ein "not"? Nuja, Gehirne arbeiten halt unterschiedlich :-D
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Bei der einen Variante muß man nur != sehen und weiß bescheit...
Beim andern muß man das not zusammen mit dem == sehen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

jens hat geschrieben:Bei der einen Variante muß man nur != sehen und weiß bescheit...
Beim andern muß man das not zusammen mit dem == sehen...
Und wo liegt jetzt der Unterschied? "not" sagt einem sofort das gleiche wie "!". Der Boolsche Folgewert soll verneint werden. Der Vergleich ist da ja eher unerheblich - oder willst Du genau folgendes ausblenden?:

Code: Alles auswählen

if(!a) {
    // wat auch immer
}
Wie oft habe ich so was schon übersehen...
im Vergelich dazu gefällt mir das explizite "not" in Python sehr gut:

Code: Alles auswählen

if not a:
    # usw.
Ob "a" nun eine einzelne Variable oder ein Ausdruck ist, spielt für mich da keine große Rolle - aber bei einer einzelnen, evtl. auch einer aus mehreren zeichen bestehenden Variablen wird die Lesbarkeit imho sehr schlecht.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich muss mich jens anschliessen.
Wenn man schon einen Ungleich-Operator hat, braucht man den nicht durch das inverse des Gleichheit-Operators zu simulieren.
Dass du das auf `!` gegen `not` herunterbrichst ist falsch, denn das ist gar nicht der Punkt.
Das Problem bei `not x == y` ist, dass man auf 2 Stellen statt auf eine achten muss, gleichzeitig muss man sich auch noch die Frage nach der Operator-Praezedenz stellen.

Der Vergleich mit C-artigem muesste uebrigens wie folgt lauten:

Code: Alles auswählen

if ( !(a == b) )
gegen

Code: Alles auswählen

 if not a == b:
P.S. die "explizite" Variante widerspricht meiner Meinung gegen folgendes aus dem Python-Zen
import this hat geschrieben:Simple is better than complex.Flat is better than nested.
Sparse is better than dense.
Readability counts.
Zuletzt geändert von cofi am Sonntag 17. Januar 2010, 15:38, insgesamt 1-mal geändert.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

if not a: nutzte ich auch immer, aber es ist was anderes als if not a == foo: und da mache ich halt lieber ein if a != foo:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten