String parsen (value)

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
Kirikkayis
User
Beiträge: 85
Registriert: Freitag 18. Januar 2019, 08:02

Hey Leute,

ich hab eine Serielle Schnittstelle von der ich Daten erhalte.
Diese sehen wie folgt aus:
's6H\x1b(s0B\x1b(s12H\x1b(s0B\r\n','Operator:30.07.1911:04\r\n','\r\n','RotordatenFall1\r\n','\r\n','a:40.00mmb:82.00mmc:40.00mm\r\n','\r\n','r1:22.00mmStatr2:49.00mm\r\n','\r\n','m1:-polar\x00m2:-polar\x00\r\n','\r\n','Tol1:2.000gmmTol2:1.000gmm\r\n','\r\n','Maschine:2Nsoll:729.1/Min\r\n','\r\n','ErgebnisseRotor:30.07.1911:04\r\n','\r\n','Lauf1Nist:729.1/Min\r\n','\r\n','Stat743.mg\r\n','\r\n','298.Grad\r\n','\r\n','8.2*Tol\r\n','\r\n','AnteilinTol.Einheiten:\r\n','16.35gmm\r\n',''
Nun brauche hier einzelne "values".
Beispiel:
Ich benötige beispielsweise die folgenden Werte: 'a', 'Nsoll' und 'Rotor' uvm.
Als Antwort reicht mir wirklich nur die einzelnen "values" also 40.00 ; 729.1 und 30.07.19 11:04

Erst dachte ich an das "String-Splitting", da ich aber bei den meisten werten keinen "trenner" wie beispielsweise ein komma oder ein Semikolon habe, bin ich mir nicht mehr ganz so sicher ob das funktioniert. (Siehe beispiel 'a:40.00mmb:82.00mmc:40.00mm\r ...'
Jemand eine Idee?
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Reguläre Ausdrücke‽
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Kirikkayis
User
Beiträge: 85
Registriert: Freitag 18. Januar 2019, 08:02

Daran arbeite ich gerade, jedoch ist das extrem hässlich und umständlich.
Es funktioniert, ist aber nicht state of the art :lol:

Ich lasse mich sehr gerne eines besseren belehren, falls ich Optimierungsvorschläge etc. habt bzw. n komplett anderes Vorgehen dann nur raus damit ;)
Nun ich gehe wie folgt vor:

Code: Alles auswählen

#block 1
regex = r"[a]:\d+.\d+" 
matches = re.finditer(regex, data, re.MULTILINE)
for matchNum, match in enumerate(matches, start=1):
   print(match.group())
    hallo = match.group()
    
    
    #block2
    regex1 = r"\d+.\d+" 
    matches = re.finditer(regex1, hallo, re.MULTILINE)
    for matchNum, match in enumerate(matches, start=1):
        print(match.group())
Ich habe mal die einzelnen "Blöcke" kommentiert, damit ich es besser erläutern kann.

Block1:
Ich erhalte einen String (data) diesen parse ich nach "a: zahl . zahl "
Da ich aber einen float brauche, muss ich das erhaltene Ergebnis erneut parsen.
Somit kommen wir zu Block 2 ...

Block2:
Ich hab ich Block1 eine Variable (hallo) hier steht das Ergebnis "a: zahl . zahl"
Dies wird erneut geparst weil ich nur einen float haben möchte.

Ich denke es ist extrem Aufwändig, zumindest so wie ich es jetzt mache.
:geek:
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kirikkayis: Da Du eine Liste mit Zeichenketten hast, macht das MULTILINE keinen Sinn. `hallo` ist ein unsinniger, schlechter Name. Und da Du `group()` bereits kennst: Gruppiere halt gleich im ersten Ausdruck das was Du extrahieren möchtest und frag dann die Gruppe ab. Ich würde auch mehr von dem was da tatsächlich im Text steht in den Ausdruck packen, denn 'a:irgendeine Zahl' könnte auch irgendwo anders mittendrin vorkommen. Das 'a' steht am Anfang und nach der Zahl folgt noch ein 'mm'.

Code: Alles auswählen

regex = re.compile(r'^a:(\d+.\d+)mm')
for line in lines:
    match = regex.search(line)
    if match:
        print(float(match.group(1)))
Wenn man da mehrere Alternativen in den regulären Ausdruck steckt, dann sollte man benannte Gruppen verwenden, sonst kommt man mit den Nummern schnell mal durcheinander.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Ungetestet:

Code: Alles auswählen

r"(\w*mm)*(?P<key>[.\w]+):(?P<value>\d+[.\d]*)*"
Edit: \w bei den mm vergessen
Kirikkayis
User
Beiträge: 85
Registriert: Freitag 18. Januar 2019, 08:02

Danke __Blackjack__ für deine Vorschläge.
Den Variablennamen habe ich erst mal random gesetzt gehabt (zum testen).
Bzgl. MULTILINE hast du recht, da habe ich mich in der Doku um eine Zeile verlesen :cry:

Bezüglich deiner Anmerkung, das "a" öferts vorkommen könnte.
Ein solches Problem habe ich nicht, die Datei ist Statisch.

@sparrow, kannst du mir deine Zeile Code Erläutern bitte?
Es ist ein regex für das Beispiel um "a" zu parsen, wenn ich es richtig herausgelesen habe ?
Oder Irre ich mich?

Danke.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Mit dem Regex solltest du alle Key-Value-Paare ohne Anhängsel an die Werte (sprich Einheiten) bekommen. Ich dachte, das wolltest du?
Kirikkayis
User
Beiträge: 85
Registriert: Freitag 18. Januar 2019, 08:02

Mit deiner Lösung kann ich "a" , "b" und "c" problemlos parsen.

Wie sieht es mit Rotor als bspl aus?
Oder mit 'AnteilinTol.Einheiten: ...'
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Wie wäre es, wenn du es einfach ausprobierst?

Und hier eine Variante, die auch nicht die Minuten vergisst:

Code: Alles auswählen

r"(\w*mm)*(?P<key>[.\w]+):(?P<value>\d+[.\d]*(:\d\d)?)*"
Benutzeravatar
__blackjack__
User
Beiträge: 14045
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kirikkayis: Das 'a:' nicht öfters vorkommen ist eine Annahme die man nicht so pauschal treffen sollte wenn man sich *einfach* gegen so einen Fall absichern kann. Irgendwann ändert sich dann doch mal was und es muss ja nicht nur ein einzelnes 'a' sein – sondern Deine Suche hätte ja auch alles als 'a:' gefunden das mit einem a vor dem Doppelpunkt aufhört, also 'extrema:' beispielsweise hättest Du ja auch als 'a:' gefunden.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten