Benutzer mit den meisten Antworten
String zerlegen

Frage
-
Hallo zusammen,
in VB.net (VS2013) bekomme ich folgenden String geliefert:
[Serial Number], A4Y4021005668 [Send Date], 05/08/2014 [Total Counter], 4607 [Total Color Counter], 551 [Total Black Counter], 4056 [Total Scan/Fax Counter], 718
Wie komme ich am einfachsten und am schnellsten an die Werte, die rechts von den Bezeichnern stehen?
Die Serial A4Y4021005668 und das 05/08/2014 sowie die Zahlen der Counter interessieren mich.
Vielen Dank schon im Voraus.
Servus
Winfried
Gruppenrichtlinien
WSUS Package Publisher
HowTos zum WSUS Package Publisher
NNTP-Bridge für MS-Foren
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!
- Bearbeitet powerzone3000 Freitag, 8. August 2014 13:23
- Als Antwort markiert Winfried.Sonntag Montag, 11. August 2014 09: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- Bearbeitet Tom Lambert (Koopakiller)Moderator Freitag, 8. August 2014 14:54
- Als Antwort markiert Winfried.Sonntag Montag, 11. August 2014 10:05
Alle 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!
- Bearbeitet powerzone3000 Freitag, 8. August 2014 13:23
- Als Antwort markiert Winfried.Sonntag Montag, 11. August 2014 09: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- Bearbeitet Tom Lambert (Koopakiller)Moderator Freitag, 8. August 2014 14:54
- Als Antwort markiert Winfried.Sonntag Montag, 11. August 2014 10:05
-
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 -
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")
- Bearbeitet powerzone3000 Montag, 11. August 2014 09:48
-
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- Bearbeitet Winfried.Sonntag Montag, 11. August 2014 10:03 Fehler eingestanden
-
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.
-
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
- Bearbeitet Winfried.Sonntag Montag, 11. August 2014 10:58 Nachtrag