2016-09-23 14 views
0

ich eine Zeichenfolge, die wie folgt aussieht:Python: regex - fangen variable Anzahl von Gruppen

TABLE_ENTRY.0[hex_number]= <FIELD_1=hex_number, FIELD_2=hex_number..FIELD_X=hex> 
TABLE_ENTRY.1[hex_number]= <FIELD_1=hex_number, FIELD_2=hex_number..FIELD_Y=hex> 

Anzahl der Felder ist nicht bekannt und variiert von Eintrag zu Eintrag, möchte ich jeden Eintrag erfassen separat mit allen seine Felder und ihre Werte.

ich kam mit:

([A-Z_0-9\.]+\[0x[0-9]+\]=)(0x[0-9]+|0):\s+<(([A-Z_0-9]+)=(0x[0-9]+|0)) 

, die den Tabelleneintrag übereinstimmt und das erste Feld, aber ich weiß nicht, wie für eine variable Anzahl von Feldern zu berücksichtigen.

eingabe:

ENTRY_0[0x130]=0: <FIELD_0=0, FIELD_1=0x140... FIELD_2=0xff3> 

ausgegeben werden soll:

ENTRY 0: 
     FIELD_0=0 
     FIELD_1=0x140 
     FIELD_2=ff3 
ENTRY 1: 
     ... 
+1

Was ist die endgültige Ausgabe, die Sie suchen? –

+0

Geben Sie ein Beispiel in der Frage – susdu

+0

Können Sie ein konkretes Beispiel geben? Der Text in Ihrer Frage scheint eine Art Syntaxbeschreibung zu sein, kein Beispiel, oder? – phynfo

Antwort

3

Kurz gesagt, es ist unmöglich, all dies in der re Motor zu tun. Sie können nicht mehr Gruppen dynamisch generieren. Es wird alles in einer Gruppe zusammengefasst.

import re 
input_str = ("TABLE_ENTRY.0[0x1234]= <FIELD_1=0x1234, FIELD_2=0x1234, FIELD_3=0x1234>\n" 
      "TABLE_ENTRY.1[0x1235]= <FIELD_1=0x1235, FIELD_2=0x1235, FIELD_3=0x1235>") 
results = {} 
for match in re.finditer(r"([A-Z_0-9\.]+\[0x[0-9A-F]+\])=\s+<([^>]*)>", input_str): 
    fields = match.group(2).split(", ") 
    results[match.group(1)] = dict(f.split("=") for f in fields) 

>>> results 
{'TABLE_ENTRY.0[0x1234]': {'FIELD_2': '0x1234', 'FIELD_1': '0x1234', 'FIELD_3': '0x1234'}, 'TABLE_ENTRY.1[0x1235]': {'FIELD_2': '0x1235', 'FIELD_1': '0x1235', 'FIELD_3': '0x1235'}} 

Der Ausgang wird nur ein großer dict sein, bestehend aus einem Tabelleneintrag zu einem dict von seinen Feldern: Sie sollten die Ergebnisse wie so neu analysieren.

Es ist auch eher convinient wie Sie dies tun können:

Ich schlage vor, persönlich Abstreifen „TABLE_ENTRY“, wie es eintönig ist, aber wie Sie wollen.

+0

Jeden Tag entdecke ich wieder, wie mühelos Python ist, danke. – susdu

+0

Wenn ich die neue Zeile aus der Eingabezeichenkette entferne, erfasst sie nicht mehr 2 Übereinstimmungen, warum ist das so? Ich bekomme: ('TABLE_ENTRY.0', '0x3242', 'FIELD_1 = 0x1234, FELD_2 = 0x1234, FIELD_3 = 0x1234> TABLE_ENTRY.1 [0x1235] = 0x98789: susdu

+0

sollte sein \ s + <([^>] *)> anstelle von \ s + <(.*)> – susdu

1

Verwenden einer Einfanggruppe für untauglich Längen match:

([A-Z_0-9\.]+\[0x[0-9]+\]=)\s+<(([A-Z_0-9]+)=(0x[0-9]+|0),\s?)*([A-Z_0-9]+)=(0x[0-9]+|0) 

Der folgende Teil jeder Anzahl von Feldern übereinstimmt mit Nachkommastellen und Leerzeichen

(([A-Z_0-9]+)=(0x[0-9]+|0),\s?)* 

Und ([A-Z_0-9]+)=(0x[0-9]+|0) wird das neueste Feld übereinstimmen.

Demo: https://regex101.com/r/gP3oO6/1

Hinweis: Wenn Sie nicht wollen, einige Gruppen, die Sie besser nicht-Erfassung von ?: Zugabe bei der Leitung von Capture-Gruppen zu verwenden ((?: ...)) und beachten Sie, dass (0x[0-9]+|0):\s+ als Statist in. Ihre Regex (basierend auf Ihrem Eingabemuster)