none
String zerlegen RRS feed

Antworten

  • Hallo miteinander,

    ich habe mal etwas mit Regulären Ausdrücken herumgespielt, damit lässt sich das eigentlich ganz gut bewerkstelligen.

    Damit ist es in wenigen Zeilen erledigt, der Code ist nur evtl nicht ganz so gut lesbar.

    Um einen einzelnen Wert anhand des Namens zu bekommen könnte man so etwas machen:

    Private Function GetValue(ByVal input As String, ByVal name As String) As String
    
        Dim pattern As String = String.Format("\[{0}], (\S+)", Regex.Escape(name))
        Dim myRegex As New Regex(pattern)
        Dim myMatch As Match = myRegex.Match(input)
    
        Return myMatch.Groups(1).Value
    
    End Function

    Man kann sich aber auch relativ einfach eine komplette NameValueCollection bauen:

    Private Function GetValues(ByVal input As String) As NameValueCollection
    
        Dim result As New NameValueCollection
        Dim myRegex As New Regex("\[(.+?)], (\S+)")
        Dim myMatches As MatchCollection = myRegex.Matches(input)
    
        For i As Integer = 0 To myMatches.Count - 1
            result.Add(myMatches(i).Groups(1).Value, myMatches(i).Groups(2).Value)
        Next
    
        Return result
    
    End Function

    Für Beispiel 1 ist folgender Import erforderlich: System.Text.RegularExpressions

    Für Beispeil 2 zusätzlich: System.Collections.Specialized

    Viele Grüße und ein schönes Wochenende!




    Freitag, 8. August 2014 13:20
  • Hallo Winfried,
    wenn du sehr viele Einräge analysieren musst, dann dürfte es mit LINQ schneller gehen, als mit Regex:

    Dim dict = str.Split({"["c}, StringSplitOptions.RemoveEmptyEntries) _
                  .Select(Function(x) x.Split("]"c)) _
                  .ToDictionary(Function(x) x(0), Function(x) x(1).Trim({","c, " "c}))

    So kannst du dann jeden Wert in dict mittels dict("Schlüssel") abrufen.

    Wenn du allerdings die Möglichkeit hast die Daten in anderer Form zu bekommen, gibt vielleicht noch bessere Verarbeitungsmöglichkeiten.


    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets


    Freitag, 8. August 2014 14:54
    Moderator

Alle Antworten

  • Hi Winfried,

    ich kenne da jetzt keine Einfachere Möglichkeit als erst mal ein Trim aufs Komma zu machen und dann auf "[".

    Vielleicht besteht ja die Möglichkeit, das du den String komplett Komma separiert bekommst.

    MFG

    Björn 

    Freitag, 8. August 2014 12:47
  • Hallo miteinander,

    ich habe mal etwas mit Regulären Ausdrücken herumgespielt, damit lässt sich das eigentlich ganz gut bewerkstelligen.

    Damit ist es in wenigen Zeilen erledigt, der Code ist nur evtl nicht ganz so gut lesbar.

    Um einen einzelnen Wert anhand des Namens zu bekommen könnte man so etwas machen:

    Private Function GetValue(ByVal input As String, ByVal name As String) As String
    
        Dim pattern As String = String.Format("\[{0}], (\S+)", Regex.Escape(name))
        Dim myRegex As New Regex(pattern)
        Dim myMatch As Match = myRegex.Match(input)
    
        Return myMatch.Groups(1).Value
    
    End Function

    Man kann sich aber auch relativ einfach eine komplette NameValueCollection bauen:

    Private Function GetValues(ByVal input As String) As NameValueCollection
    
        Dim result As New NameValueCollection
        Dim myRegex As New Regex("\[(.+?)], (\S+)")
        Dim myMatches As MatchCollection = myRegex.Matches(input)
    
        For i As Integer = 0 To myMatches.Count - 1
            result.Add(myMatches(i).Groups(1).Value, myMatches(i).Groups(2).Value)
        Next
    
        Return result
    
    End Function

    Für Beispiel 1 ist folgender Import erforderlich: System.Text.RegularExpressions

    Für Beispeil 2 zusätzlich: System.Collections.Specialized

    Viele Grüße und ein schönes Wochenende!




    Freitag, 8. August 2014 13:20
  • Hallo Winfried,
    wenn du sehr viele Einräge analysieren musst, dann dürfte es mit LINQ schneller gehen, als mit Regex:

    Dim dict = str.Split({"["c}, StringSplitOptions.RemoveEmptyEntries) _
                  .Select(Function(x) x.Split("]"c)) _
                  .ToDictionary(Function(x) x(0), Function(x) x(1).Trim({","c, " "c}))

    So kannst du dann jeden Wert in dict mittels dict("Schlüssel") abrufen.

    Wenn du allerdings die Möglichkeit hast die Daten in anderer Form zu bekommen, gibt vielleicht noch bessere Verarbeitungsmöglichkeiten.


    Tom Lambert - C# MVP
    Bitte bewertet- und markiert Beiträge als Antwort. Danke.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets


    Freitag, 8. August 2014 14:54
    Moderator

  • Man kann sich aber auch relativ einfach eine komplette NameValueCollection bauen:

    Private Function GetValues(ByVal input As String) As NameValueCollection
    
        Dim result As New NameValueCollection
        Dim myRegex As New Regex("\[(.+?)], (\S+)")
        Dim myMatches As MatchCollection = myRegex.Matches(input)
    
        For i As Integer = 0 To myMatches.Count - 1
            result.Add(myMatches(i).Groups(1).Value, myMatches(i).Groups(2).Value)
        Next
    
        Return result
    
    End Function

    Für Beispiel 1 ist folgender Import erforderlich: System.Text.RegularExpressions

    Für Beispeil 2 zusätzlich: System.Collections.Specialized

    Vielen Dank, damit hat es sofort einwandfrei funktioniert. ;)

    Um auf die jeweiligen Inhalte zugreifen zu können, hab ich zusätzlich diese Zeile noch benötigt:

    'NameValueCollection füllen

    Dim sArray As NameValueCollection = GetValues(strBody) 'Zugriff auf Inhalt der NameValueCollection cmd.Parameters.Add("@fldName", SqlDbType.VarChar, 50) cmd.Parameters("@fldName").Value = sArray(0)



    Servus
    Winfried

    Gruppenrichtlinien
    WSUS Package Publisher
    HowTos zum WSUS Package Publisher
    NNTP-Bridge für MS-Foren

    Montag, 11. August 2014 09:25
  • Hallo Winfried,
    schön, dass dir meine Antwort weitergeholfen hat.

    Übrigens: Nachdem es sich bei der Rückgabe der Funktion um eine NameValueCollection (und nicht nur um ein einfaches Array) handelt, kannst du auf die Elemente sogar per Name zugreifen:

    Dim values As NameValueCollection = GetValues(strBody)
    '...
    cmd.Parameters("@fldName").Value = values("Serial Number")

    So hast du auch keine Probleme, wenn sich die Reihenfolge der Elemente im String mal ändern sollte.


    Gleiches gilt übrigens für die Variante von Tom:

    Dim values = strBody.Split({"["c}, StringSplitOptions.RemoveEmptyEntries) _
                  .Select(Function(x) x.Split("]"c)) _
                  .ToDictionary(Function(x) x(0), Function(x) x(1).Trim({","c, " "c}))
    
    '...
    
    ' Zugriff:
    values("Serial Number")

    Montag, 11. August 2014 09:42
  • wenn du sehr viele Einräge analysieren musst, dann dürfte es mit LINQ schneller gehen, als mit Regex:

    Dim dict = str.Split({"["c}, StringSplitOptions.RemoveEmptyEntries) _
                  .Select(Function(x) x.Split("]"c)) _
                  .ToDictionary(Function(x) x(0), Function(x) x(1).Trim({","c, " "c}))

    So kannst du dann jeden Wert in dict mittels dict("Schlüssel") abrufen.

    Wenn du allerdings die Möglichkeit hast die Daten in anderer Form zu bekommen, gibt vielleicht noch bessere Verarbeitungsmöglichkeiten.

    Die Anzahl der Einträge kann vollkommen vernachlässigt werden.

    Wenn ich dein Beispiel ausführen möchte, bekomme ich diese Fehlermeldung:

    Fehler    1    Für den Parameter "Number" von "Public Function Str(Number As Object) As String" wurde kein Argument angegeben.    

    Ich hab es dann so versucht:

    Dim dict = Str(Split({"["c}, CStr(StringSplitOptions.RemoveEmptyEntries)) _
                               .Select(Function(x) strBody.Split("]"c)) _
                               .ToDictionary(Function(x) strBody(0), Function(x) x(1).Trim({","c, " "c})))

    Bekomme allerdings die Fehlermeldung:

    "Das Argument Number kann nicht in einen numerischen Wert konvertiert werden."

    strBody ist übrigens der String der die Bezeichner und die Werte enthält. Gerne würde ich das verstehen, kannst Du mir auf die Sprünge helfen?

    Vielen Dank schon im Voraus.

    EDIT: powerzone3000 hat mir die Augen geöffnet und mir meinen Fehler aufgezeigt, entschuldigung, natürlich läuft auch deine Funktion einwandfrei. Danke. ;)


    Servus
    Winfried

    Gruppenrichtlinien
    WSUS Package Publisher
    HowTos zum WSUS Package Publisher
    NNTP-Bridge für MS-Foren


    Montag, 11. August 2014 09:48
  • Hallo,

    ich habe oben noch ein beispiel für Tom's Linq-Variante hinzugefügt. str muss mit deiner String-Variablen ersetzt werden, in deinem Fall also strBody.

    Dann erhälst du ein Dictionary zurück, das kannst du im prinzip genau so verwenden wie die NameValueCollection.

    Montag, 11. August 2014 09:55
  • Hallo,

    ich habe oben noch ein beispiel für Tom's Linq-Variante hinzugefügt. str muss mit deiner String-Variablen ersetzt werden, in deinem Fall also strBody.

    Wo hast Du das Beispiel eingefügt?

    EDIT: Jetzt weiß ich was Du meinst, Danke. ;)



    Dann erhälst du ein Dictionary zurück, das kannst du im prinzip genau so verwenden wie die NameValueCollection.


    Nach Testläufen mit Echtdaten ist auch noch aufgefallen dass die Variante von Tom sogar ein fehlendes Leerzeichen nach "[Serial Number]," problemlos schluckt. Das kann ich leider ebenfalls nicht steuern. Vielen Dank trotzdem für alle Antworten, ihr habt mir sehr damit geholfen. ;)


    Servus
    Winfried

    Gruppenrichtlinien
    WSUS Package Publisher
    HowTos zum WSUS Package Publisher
    NNTP-Bridge für MS-Foren



    Montag, 11. August 2014 10:55