Struktur Auswerten...

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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.?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

OK, danke... Ich denke ich werde dann doch mit RE experimentieren....

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

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
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

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
:-)
Zuletzt geändert von gerold am Donnerstag 28. April 2005, 08:10, insgesamt 2-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Chapeau! (hab ich aber nicht getestet)
mawe
Python-Forum Veteran
Beiträge: 1209
Registriert: Montag 29. September 2003, 17:18
Wohnort: Purkersdorf (bei Wien [Austria])

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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']

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
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.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

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.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten