Regex Split Wert und Einheit

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Elanda.

    Regex Split Wert und Einheit

    Ich bitte um Hilfe bei folgendem Problem.
    Mit Regex möchte ich den Wert und die Maßeinheit trennen wobei der String unterschiedlich aussehen kann.
    Beispiele:

    10g
    12,3ml
    127,35 Kg
    0,456 g/cm³

    Ich habe leidern noch keine Pattern gefunden, der mir den numerischen Wert und die Maßeiheit in allen Fällen zuverlässig ausgibt.
    Könnt ihr mir bitte helfen!

    Danke!
    "(?:(-?[0-9,]+)\s*([^0-9 ]+))"

    Deiner Beschreibung nach sollte das hier passen!
    Jedoch kann man ohne genaue Beschreibung nur sehr limitiert arbeiten, also ist das alles was ich jetzt machen konnte!

    Gruppe 1: Der Wert
    Gruppe 2: Die Bezeichnung

    Achte darauf das die Bezeichnung keine Leerzeichen enthält da diese den Regex starten und beenden, wenn du aber Maßeinheiten mit Leerzeichen brauchst, musst du die Maximale Länge der Werte limitieren. (das geht mit {n,m})

    Somit habe ich dir das Muster geliefert, du wirst aber einen Fehler aufgezeigt bekommen, wie du denn reparierst wirst du schon rausfinden ;) (kleiner Tipp, es handelt sich um ein 2 mal hintereinander folgendes Zeichen welches ich jetzt mal absichtlich ausgelassen habe)

    Ps:
    Bei Interesse, dieses Werkzeug ist sehr Hilfreich beim Testen und Auswerten von Regex-Mustern:
    regex101.com/
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------
    @doLob Im Ernstfall suchst Du das erste Zeichen, das nicht "-0123456789,." ist (Punkt oder Komma je nach Ländereinstellung. Da sind die Leerzeichen egal.
    numerischer string auf nichtnumerische Zeichen prüfen
    docs.microsoft.com/de-de/dotne…ber?view=netframework-4.8
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Elanda
    Vielen Dank für die Vorgabe. Die funktioniert bei mir auch ohne Änderung. Nur das er 4 Gruppen zurück gibt und natürlich Zahlen in der
    Maßeinheit ignoriert werden was ich aber ändern konnte. Warum gibt Regex.Split vor und hinter den gesuchten Werten jeweils eine leere
    Gruppe aus?

    Zum Verständnis: Ich muß importierte Daten in meiner Anwendung weiterverarbeiten. Als Quelle bekomme ich oft unterschiedlich formatierte
    Daten. Fakt ist, das es immer eine mit oder ohne führendes Leerzeichen importierte Fließkommazahl mit variablen Stellen vor und hinter dem
    Komma ist und dann wiederum mit oder ohne Leerzeichen folgend die Maßeinheit die dann selber zwar keine Leerzeichen mehr enthält, jedoch aus allen
    denkbaren Zeichen bestehen kann. g/cm³ wird auch mal g/cm3 geschrieben.
    MfG

    @RodFromGermany
    Das funktioniert auch, aber ich bin gerade dabei mich mit Regex auseinanderzusetzen. Deshalb möchte ich damit eine Lösung probieren.
    Danke

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „doLob“ ()

    Für welche Eingabe bekommst du denn diese Ausgabe?
    Mein Regex war nur ein Basismuster, er macht das nötigste, aber behandelt keine Ausnahmen die man jedoch zuerst kennen sollte!
    Manche Programme handeln damit unterschiedlich, ich kenne mich mit VB.NET nicht aus, da könnten kleine Unterschiede bestehen in Gegensatz zu dem was ich gewohnt bin.
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------
    @Elanda
    In dem Online Tester den du verlinkt hast funzt es ja einwandfrei. Leider kann man da ja auch nicht vb.net einstellen.
    Im vb.net framework 4.7.2, welches ich nutze, ist es ganz egal welche der Eingaben ich probiere. Es gibt immer erst eine leere Gruppe 0, dann
    in Gruppe 1 den gesuchten Wert, in Gruppe 2 die gesuchte Einheit und dann die leere Gruppe 3.
    Ich kann ja damit weiterarbeiten aber ich hätte gern Verstanden was da passiert.

    MfG

    Elanda schrieb:

    "(?:(-?[0-9,]+)\s*([^0-9 ]+))"

    Hmm - bischen eigenartig, dass alles in eine (?:)-Gruppe eingeschlossen ist - nach meinen Versuchen funzt es auch ohne:
    (-?[0-9,]+)\s*([^0-9 ]+)
    Zu beachten auch, dass der Online-RegexTester kein Regex.Split() ausführt, sondern ein Regex.Matches()
    Das ist ein entscheidender Unterschied!
    Wenn ich mt dem Pattern ein Regex.Split() ausführe bekomme ich auch dein komisches Ergebnis, was ich auch nicht verstehe.
    Also die Matches sind im OnlineRegextester gut erklärt - aber die verwendest du ja garnet.
    Und Regex.Split() verhält sich scheints anders, als ich gedacht hab:
    Bei Regex-Pattern (-?[0-9,]+)\s*([^0-9 ]+) und TestString 0,456 g/cm³ hätte ich für Regex.Split(TestString, pattern) zwei leere Segmente als Ergebnis erwartet. Denn der Pattern matcht auf die komplette Eingabe, und Split() sollte den Text davor (leer) und danach (leer) erbringen.
    Stattdessen bekomme ich 4 Segmente:

    Quellcode

    1. (leer)
    2. 0,456
    3. g/cm³
    4. (leer)
    Also der Inhalt der Gruppen findet sich als gesplittetes Segment in der Ausgabe, was nach meim Verständnis von Regex.Split() nicht sein sollte.
    Gut - da kann ich wohl hinzu-lernen - mit Regex.Split() habich tatsächlich kaum je mal was gemacht.
    Auch in deinem Fall würde ich einfach mal davon abraten. Benutze Regex.Matches() und werte die Gruppen in den gefundenen Matches aus.
    Vom Pattern (-?[0-9,]+)\s*([^0-9 ]+)
    Dann verstehe ich was der Regex macht, und könnte es auch erklären.

    So, jetzt Doku gelesen: docs.microsoft.com/de-de/dotne…lit?view=netframework-4.8
    Split() verhält sich halt so komisch, wenn im Pattern Gruppen definiert sind. Und mit mehreren Gruppen im Pattern scheints noch komischer zu werden, steht inne Doku:

    Microsoft schrieb:

    ...Wenn das Muster für reguläre Ausdrücke jedoch mehrere Sätze von Erfassungs Klammern enthält, hängt das Verhalten dieser Methode von der Version der .NET Framework ab...
    Also jetzt habich sogar einen Grund, von Regex.Split() abzuraten (ausser, dass ich das nicht gut kenne). :P

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Text.RegularExpressions
    4. Module Module1
    5. Sub Main()
    6. Dim t(4) As String
    7. t(1) = " 10g"
    8. t(2) = "12,3ml"
    9. t(3) = "127,35 Kg"
    10. t(4) = "0,456 g/cm³ "
    11. Dim tmp As String
    12. For i As Integer = 1 To 4
    13. tmp = Regex.Replace(t(i), "([0-9,]+)(\x20|)([^0-9]+)", "$1-$3", RegexOptions.Singleline Or RegexOptions.Multiline)
    14. Debug.Print(t(i))
    15. Debug.Print(tmp)
    16. Dim sp() As String
    17. sp = tmp.Split("-"c)
    18. Debug.Print(">>" & sp(0).Trim() & "<<" & " >>" & sp(1).Trim() & "<<" & vbCrLf)
    19. Next
    20. End Sub
    21. End Module

    ErfinderDesRades schrieb:

    Elanda schrieb:

    "(?:(-?[0-9,]+)\s*([^0-9 ]+))"


    Zu beachten auch, dass der Online-RegexTester kein Regex.Split() ausführt, sondern ein Regex.Matches()


    Ich wäre auch davon ausgegangen, dass match verwendet wird.
    Keine Ahnung was Regex.split ist, kenne ich nicht.

    Und die non-capturing group verwende ich immer dafür damit der Regex etwas mehr eingekapselt aussieht, mir persönlich zeigt das auf den ersten Blick das alles zusammengehört!
    Man programmiert nicht nur mit Logik sondern auch mit dem Auge! ;)
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    doLob schrieb:

    Ich habe mal ohne den pattern zu ändern auf Regex.matches umgestellt und bekomme immer nur eine Gruppe mit dem gesamten String.

    Probierma den von mir angegebenen Pattern.
    Deswegen habe ich ihn ja angegeben.

    Ich verwende einen selbstgeschriebenen RegexTester, der tatsächlich vb.net: Regex.Split() und Regex.Matches() ausführt.
    Scheinbar tickt der Online-RegexTester ein bischen anders als dann die .net Regex-Klasse, und auch Elanda scheint Regexe in einem anneren Kontext zu verwenden als .Net.

    PS: Eierleins Regex scheint mir Negativ-Zahlen nicht zu berücksichtigen.
    aber vlt. ist das grad gut, weil solche in deim Kontext nicht sinnvoll sind.

    Übrigens, wenn Eierleins Code bei dir funzt, solltest du dein System umstellen. Der VB6-GeneralImport ist der Programmierkunst äusserst abträglich.
    Visual Studio - Empfohlene Einstellungen

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ich hab mal eine vereinfachte Entsprechung des Eierlein-Samples gebastelt, auch um zu zeigen, wie das mitte Matches gemeint ist:

    VB.NET-Quellcode

    1. Friend Sub RegexMatchTests()
    2. Dim t = {"-10g", " 10g", "12,3ml", "127,35 Kg", "0,456 g/cm³ "}
    3. For Each tmp In t
    4. Dim mt = Regex.Match(tmp, "(-?[0-9,]+)\s*([^0-9 ]+)")
    5. Debug.Print($">>{mt.Groups(1).Value}<< >>{mt.Groups(2).Value}<<")
    6. Next
    7. End Sub
    Ausgabe:

    Quellcode

    1. >>-10<< >>g<<
    2. >>10<< >>g<<
    3. >>12,3<< >>ml<<
    4. >>127,35<< >>Kg<<
    5. >>0,456<< >>g/cm³<<
    IMO sind weder Regex.Split() noch Regex.Replace() angezeigt, sondern wie gesagt Regex.Match() oder - wenn man einen String mit mehreren Treffern hat: Regex.Matches()
    @ErfinderDesRades
    Das funktioniert so bei mir nun auch. Den Pattern musste ich nur noch anpassen, da in der Maßeinheit auch Ziffern vorkommen könnten.
    Vielen Dank

    @Alle
    Schön das es mehrere Wege zum gewünschten Ergebnis gibt obwohl mir noch nicht alle ganz klar sind. Mit dem hier aufgezeigten kann ich aber erstmal gut
    weiterarbeiten.
    Bleibt Gesund !!
    MfG
    Ha, spannend!
    In einem .NET Regex tester scheint meins tatsächlich nicht zu funktionieren!

    Wieder mal interessant wie verschieden die in ihren eigenen Umgebungen funktionieren.
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------