Seite 1 von 1

Struktur Auswerten...

Verfasst: Mittwoch 27. April 2005, 13:45
von jens
Habe eine Struktur Auszuwerten:

Code: Alles auswählen

class Mission
{
   [...]
   addOns[]=
   {
      "lsr_rang",
      [...]
      "ofpec_blood"
   };
   [...]
   addOnsAuto[]=
   {
      "lsr_rang",
      [...]
      "BMP2"
   };
   [...]
}; 
Mir geht es um die Einträge bei addOns und addOnsAuto. Ich könnte mir vorstellen, das es mit RE recht einfach ist daran zu kommen. Gibt es dennoch auch andere, evtl. sinnvollere Möglichkeiten?

Verfasst: Mittwoch 27. April 2005, 15:55
von CM
Hoi Jens,

was genau meinst Du mit "Struktur auswerten"? Alles zwischen den geschweiften Klammern hinter dem Gleichheitszeichen auslesen? Wie?
Insgesamt klingt das schon nach einem Problem für regular expressions, aber u.U. geht das auch mit einem Linewalk a la: for line in ....
Aber Du solltest vielleicht das Problem erst einmal etwas spezifizieren.

Gruß,
Christian

Verfasst: Mittwoch 27. April 2005, 16:06
von jens
Sorry... Mir geht es um die Listeneinträge die definiert werden.

Im obrigen Beispiel entsprechent möchte ich das folgende raus haben:

Code: Alles auswählen

addOns = [ "lsr_rang", ... , "ofpec_blood" ]
addOnsAuto = [ "lsr_rang", ... , "BMP2" ]
Eigentlich ist die verwendete Syntax in der die Listeneinträge abgelegt werden sehr klar... Deswegen frage ich mich ob es eine elegantere Lösung außer RE gibt. (Wobei RE wahrscheinlich die schnellere zu realisierende ist)
Gibt es evtl. in Python selber schon einen Parser den man auf diese Syntax "konfigurieren" kann?
Verkompliziere ich die Dinge evtl.?

Verfasst: Mittwoch 27. April 2005, 16:17
von CM
Grundsätzlich gilt ja: Keine Parser selber schreiben, weil es gibt sie schon. Die Recherche darfst Du allerdings selber machen :twisted:
Ansonsten: Unbedingt REs nehmen. Zwei matched groups und Du bist von allem ab. Das verlangt zwar etwas mehr Hirnschmals spart Dir aber einige Zeilen Code und Du weißt in drei Monaten auch noch genau was Du gemacht hast.

Gruß,
Christian

Verfasst: Mittwoch 27. April 2005, 16:19
von jens
OK, danke... Ich denke ich werde dann doch mit RE experimentieren....

Verfasst: Mittwoch 27. April 2005, 16:34
von CM
Nachtrag:
Schau doch mal hier: http://www.python.org/moin/LanguageParsing
Und wenn Du da nichts findest, stelle Deine Frage doch einfach mal in der Mailingliste der SIG.

Warum selber schreiben, was es schon gibt?

Gruß,
Christian

Verfasst: Mittwoch 27. April 2005, 16:37
von gerold
jens hat geschrieben:OK, danke... Ich denke ich werde dann doch mit RE experimentieren....
Fertig! :P

Code: Alles auswählen

import re

data = """class Mission
{
   [...]
   addOns[]=
   {
      "lsr_rang",
      "ofpec_blood"
   };
   [...]
   addOnsAuto[]=
   {
      "lsr_rang",
      "BMP2"
   };
   [...]
};"""

gefunden = re.findall(
   "addOns[].*?{(.*?)}|addOnsAuto[].*?{(.*?)}", 
   data.replace("\n", ""), 
   re.I | re.M
)

addOns = []
for item in gefunden[0].split(","):
   addOns.append(item.replace('"', '').strip())
addOnsAuto = []
for item in gefunden[1].split(","):
   addOnsAuto.append(item.replace('"', '').strip())

print addOns
print addOnsAuto
lg
Gerold
:-)

Verfasst: Mittwoch 27. April 2005, 16:39
von CM
Chapeau! (hab ich aber nicht getestet)

Verfasst: Mittwoch 27. April 2005, 16:45
von mawe
Hi!

Eine Version ohne Regex. So kompliziert wie nur möglich, scheint aber zu funktionieren :wink: (das Ergebnis wird in ein Dictionary gespeichert):

Code: Alles auswählen

f = file("text.txt","r")
dic = {}
ads = []
for line in f:
    if '{' in line: continue
    elif '};' in line:
        if chunk:
            dic[chunk] = ads
        chunk = ""
        ads = []
    elif '[]=' in line:
        chunk = line.strip().strip('[]=')
        ads = []
    else:
        ad = line.strip().strip('".').strip('[]')
        ads.append(ad)
print dic
Gruß, mawe

Verfasst: Mittwoch 27. April 2005, 16:46
von jens
CM hat geschrieben:Schau doch mal hier: http://www.python.org/moin/LanguageParsing
Ne, danke... Ich hab mir das die hälte angeschaut, aber nix wirklich verstanden :oops: Ich denke RE ist in diesem Fall die einfachste Variante...

Verfasst: Mittwoch 27. April 2005, 17:05
von gerold
mawe hat geschrieben: Eine Version ohne Regex. So kompliziert wie nur möglich, scheint aber zu funktionieren
Hi mawe!

Und ich dachte mal, Regular Expressions sind kompliziert :wink: :D :lol:

lg
Gerold
:-)

Verfasst: Mittwoch 27. April 2005, 17:20
von jens
gerold hat geschrieben:Fertig! :P
Wow, ich hab noch garnicht angefangen...
In deiner Variante ist allerdings auch ein fehler :lol:
Sie spuckt nämlich zweimal das selbe raus:
['lsr_rang', 'ofpec_blood']
['lsr_rang', 'ofpec_blood']
Meine Variante geht in zwei Schritten vor:

Code: Alles auswählen

import re

data = """class Mission
{
   [...]
   addOns[]=
   {
      "lsr_rang",
      "ofpec_blood"
   };
   [...]
   addOnsAuto[]=
   {
      "lsr_rang",
      "BMP2"
   };
   [...]
};"""

def get( typ, data ):
    # Erst alles in den {}-Klammern rausfischen
    result = re.findall(
        typ+'\[\]=.*?{(.*?)}',
        data,
        re.S
    )
    # Alle Werte in "" zurück geben
    return re.findall( r'"(.*?)"', result[0] )

print get( "addOns", data )
print get( "addOnsAuto", data )
Ausgabe:
['lsr_rang', 'ofpec_blood']
['lsr_rang', 'BMP2']

Verfasst: Mittwoch 27. April 2005, 17:35
von gerold
jens hat geschrieben: In deiner Variante ist allerdings auch ein fehler :lol:
Sie spuckt nämlich zweimal das selbe raus:
['lsr_rang', 'ofpec_blood']
['lsr_rang', 'ofpec_blood']
Sorry, ist jetzt ausgebessert. Das war mal wieder so ein Copy&Paste-Fehler.

lg
Gerold
:-)

Verfasst: Mittwoch 27. April 2005, 22:37
von BlackJack
gerold hat geschrieben:

Code: Alles auswählen

gefunden = re.findall(
   "addOns[].*?{(.*?)}|addOnsAuto[].*?{(.*?)}", 
   data.replace("\n", ""), 
   re.I or re.M
)
Die letzte Zeile tut nicht das was sie soll:

Code: Alles auswählen

In [8]: re.I or re.M
Out[8]: 2

In [9]: re.I | re.M
Out[9]: 10
Der ``or``-Operator gibt eines der beiden Objekte zurück (im vorliegenden Fall das `re.I`), während ``|`` eine Oder-Verknüpfung der Bits von zwei Zahlen ist.

Verfasst: Donnerstag 28. April 2005, 08:08
von gerold
BlackJack hat geschrieben: Die letzte Zeile tut nicht das was sie soll:

Code: Alles auswählen

In [8]: re.I or re.M
Out[8]: 2

In [9]: re.I | re.M
Out[9]: 10
Der ``or``-Operator gibt eines der beiden Objekte zurück (im vorliegenden Fall das `re.I`), während ``|`` eine Oder-Verknüpfung der Bits von zwei Zahlen ist.
Hi BlackJack!

Danke! :P

Das erklärt, das mir unerklärliche Verhalten, einiger meiner RE-Funktionen. Das ist auch der Grund gewesen, weshalb ich oft vorher mit "replace" die Zeilenumbrüche entferne, obwohl diese mit re.M kein Problem mehr sein dürften. Da liest man vor dem Schlafen die Python-Doku und hat am nächsten Tag nur mehr "Oder" im Kopf :wink:

Das war wieder mal ein super Hinweis.

lg
Gerold
:-)

PS: Ich ändere meinen Beispielcode, damit nicht noch jemand den gleichen Fehler macht.