Seite 1 von 2

Regulärer Ausdruck: verschachtelte Klammer

Verfasst: Samstag 16. Januar 2010, 16:26
von Jack Daniels
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

Verfasst: Samstag 16. Januar 2010, 16:33
von DasIch
Rekursion geht mit regulären Ausdrücken nicht, insofern musst du "dass umständlicher schreiben".

Verfasst: Samstag 16. Januar 2010, 16:45
von HWK
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

Verfasst: Samstag 16. Januar 2010, 22:53
von snafu
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.

Verfasst: Samstag 16. Januar 2010, 23:06
von Panke
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.

Verfasst: Samstag 16. Januar 2010, 23:29
von snafu
Naja, selbst wenn es keine Regexp im ursprünglichen Sinne ist, wird hier zumindest gezeigt, was mit Ruby und Perl möglich ist.

Verfasst: Samstag 16. Januar 2010, 23:42
von Leonidas
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.

Verfasst: Sonntag 17. Januar 2010, 08:24
von snafu
Du meinst jetzt das Programmieren in Perl oder die speziell die Regexp-Grammatik in Perl?

Verfasst: Sonntag 17. Januar 2010, 10:00
von Jack Daniels
OK danke, dann werd ich das anders lösen. :)

Verfasst: Sonntag 17. Januar 2010, 10:32
von HWK
Das hilft Dir vielleicht dabei.
MfG
HWK

Verfasst: Sonntag 17. Januar 2010, 13:00
von Jack Daniels
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.

Verfasst: Sonntag 17. Januar 2010, 14:11
von cofi
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:

Verfasst: Sonntag 17. Januar 2010, 14:30
von Dav1d
wieso verwendet man eig. immer dieses hässliche if x != i-was und nicht if not x == i-was

Verfasst: Sonntag 17. Januar 2010, 14:32
von HWK

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

Verfasst: Sonntag 17. Januar 2010, 15:02
von jens
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...

Verfasst: Sonntag 17. Januar 2010, 15:05
von Hyperion
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

Verfasst: Sonntag 17. Januar 2010, 15:09
von jens
Bei der einen Variante muß man nur != sehen und weiß bescheit...
Beim andern muß man das not zusammen mit dem == sehen...

Verfasst: Sonntag 17. Januar 2010, 15:22
von Hyperion
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.

Verfasst: Sonntag 17. Januar 2010, 15:38
von cofi
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.

Verfasst: Sonntag 17. Januar 2010, 15:38
von jens
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: