Pyparsing macht es einfach, benutzerdefinierte Parser für Daten wie diese zu schreiben, und gibt geparste Daten in einem Pyparsing-Datenstrukturaufruf ParseResults zurück. ParseResults gibt Ihnen Zugriff auf Ihre geparsten Werte nach Position (wie eine Liste), nach Schlüssel (wie ein Dict) oder nach Namen, die als Python-Bezeichner nach Attribut (wie ein Objekt) funktionieren.
Ich habe meine Parsing Ihrer Daten vereinfacht, so einfach nehmen Sie alle key = value
Zeile und erstellen Sie eine Struktur mit den Schlüsselzeichenfolgen als Schlüssel. Die '..' Zeilen funktionieren großartig als Terminatoren für jedes Objekt.
Ein einfacher BNF hierfür könnte wie folgt aussehen:
object ::= attribute+ end
attribute ::= key '=' value
key ::= word composed of letters 'A'..'Z' and '-', starting with 'A'..'Z',
or a quoted string
value ::= value_string | value_number | value_word
value_word ::= a string of non-whitespace characters
value_string ::= a string of any characters in '"' quotes
value_number ::= an integer or float numeric value
end ::= '..'
einen pyparsing Parser zu implementieren, arbeiten wir unten pyparsing Unterausdrücke zu definieren. Dann verwenden wir Python '+' und '|' Operatoren niedrigerer Ebene Ausdrücke höherer Ebene diejenigen zu montieren:
import pyparsing as pp
END = pp.Suppress("..")
EQ = pp.Suppress('=')
pyparsing einige vordefinierte Ausdrücke für Zeichenfolgen in Anführungszeichen und Numerik enthält; Die Zahlen werden automatisch in Ints oder Floats umgewandelt.
value_number = pp.pyparsing_common.number
value_string = pp.quotedString
value_word = pp.Word(pp.printables)
value = value_string | value_number | value_word
Für unseren Attributschlüssel werden wir das Zwei-Argument-Formular für Word verwenden.Das erste Argument ist eine Zeichenfolge mit zulässigen führenden Zeichen, und das zweite Argument ist eine Zeichenfolge der zulässigen Körperzeichen. Wenn wir nur `Wort (alphas + '-') geschrieben haben, dann würde unser Parser" --- "als legalen Schlüssel akzeptieren.
key = pp.Word(pp.alphas, pp.alphas + '-') | pp.quotedString
Ein Attribut Definition ist nur ein Schlüssel, ein Zeichen ‚=‘, und ein Wert
attribute = key + EQ + value
Schließlich werden wir einige der komplexeren Funktionen von pyparsing verwenden. Die einfachste Form wäre nur "pp.OneOrMore (Attribut) + END", aber dies würde uns nur einen Stapel von geparsten Tokens ohne Struktur zurückgeben. Die Group-Klasse strukturiert die eingeschlossenen Ausdrücke so, dass ihre Ergebnisse als Unterliste zurückgegeben werden. Wir werden jedes Attribut als seine eigene Unterliste mit Group abfangen. Dict wendet eine Benennung auf die Ergebnisse an, wobei der Text von jedem Schlüsselausdruck als Schlüssel für diese Gruppe verwendet wird. Schließlich wird die ganze Sammlung von Attributen wieder Group'ed werden, diesmal repräsentiert alle Attribute für ein einzelnes Objekt:
object_defn = pp.Group(pp.Dict(pp.OneOrMore(pp.Group(attribute)))) + END
diesen Ausdruck zu verwenden, werden wir unser Parser definieren als:
parser = pp.OneOrMore(object_defn)
und analysieren, um die Probe Zeichenfolge mit:
objs = parser.parseString(sample)
die objs
Variable, die wir zurückbekommen wird ein pypar sing ParseResults, das wie eine Liste der gruppierten Objektattribute funktioniert. Wir können sehen nur die analysierten Attribute als Liste von Listen asList mit():
for obj in objs:
print(obj.asList())
[['"Office PSZ"', 'SYSTEM'], ['TYPE', 'PSZ'], ['HEAT-SOURCE', 'FURNACE'],
['FAN-SCHEDULE', '"HVAC Yr Schedule"'], ['COOLING-EIR', 0.233207]]
Wenn wir nicht die Dict Klasse benutzt hatte, würde dies alles haben wir bekommen würde, aber da wir tat Einsatz dict, können wir die Attribute als Python dict siehe auch:
for obj in objs:
print(obj.asDict())
{'COOLING-EIR': 0.233207, '"Office PSZ"': 'SYSTEM', 'TYPE': 'PSZ',
'FAN-SCHEDULE': '"HVAC Yr Schedule"', 'HEAT-SOURCE': 'FURNACE'}
wir können auch nach Name Zugriff benannte Felder, wenn sie als Python-IDs arbeiten. In Ihrem Beispiel ist "TYPE" die einzige legale ID, so dass Sie sehen können, wie Sie es hier ausdrucken können. Dort ist auch eine dump()
Methode, die die Ergebnisse in Listenform gibt, gefolgt von einer eingerückten Liste von definierten Schlüsselpaaren. (Ich habe auch gezeigt, wie Sie die Liste verwenden können und DIKT Typ Zugriff direkt auf die ParseResults Objekt, ohne zu konvertieren oder dict-Typen zur Liste):
for obj in objs:
print(obj[0])
print(obj['FAN-SCHEDULE'])
print(obj.TYPE)
print(obj.dump())
['"Office PSZ"', 'SYSTEM']
"HVAC Yr Schedule"
PSZ
[['"Office PSZ"', 'SYSTEM'], ['TYPE', 'PSZ'], ['HEAT-SOURCE', 'FURNACE'],
['FAN-SCHEDULE', '"HVAC Yr Schedule"'], ['COOLING-EIR', 0.233207]]
- "Office PSZ": 'SYSTEM'
- COOLING-EIR: 0.233207
- FAN-SCHEDULE: '"HVAC Yr Schedule"'
- HEAT-SOURCE: 'FURNACE'
- TYPE: 'PSZ'
Hier ist der vollständige Parser-Code für Sie arbeiten von:
import pyparsing as pp
END = pp.Suppress("..")
EQ = pp.Suppress('=')
value_number = pp.pyparsing_common.number
value_string = pp.quotedString
value_word = pp.Word(pp.printables)
value = value_string | value_number | value_word
key = pp.Word(pp.alphas, pp.alphas+"-") | pp.quotedString
attribute = key + EQ + value
object_defn = pp.Group(pp.Dict(pp.OneOrMore(pp.Group(attribute)))) + END
parser = pp.OneOrMore(object_defn)
objs = parser.parseString(sample)
for obj in objs:
print(obj.asList())
for obj in objs:
print(obj.asDict())
for obj in objs:
print(obj[0])
print(obj['FAN-SCHEDULE'])
print(obj.TYPE)
print(obj.dump())
Es klingt wie Sie ein Objekt als * Container * verwenden möchten, dh als einen organisierten Ort, um eine Sammlung von Daten zu speichern. Sie scheinen einen Container zu haben, mit dem Sie benannte Datenelemente sammeln können. Wenn dies zutrifft, könnte es einfacher sein, ein Wörterbuch zu verwenden. Man könnte sagen: 'Office_PSZ = {'TYPE': 'PSZ', 'HEAT-SOURCE': 'ELECTRIC', ...}' Wenn Sie das Dokument 'dict' lesen, werden Sie feststellen, dass Sie beliebige Elemente hinzufügen können ein Wörterbuch, greifen Sie individuell auf sie zu, und so weiter. –