Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Parsing a String

Status
Not open for further replies.

Billx1

Technical User
Jan 28, 2011
44
US
Hello group,

I have encountered something that I cannot figure out. I have a piece of equipment that sends data via RS-232 to my computer.
I can receive it ok and it is saved as a string similar to this

Stack=3 Ask=1 Base=0.0 Ast="Mary Smith(201)" Bst="Jim Smith(202)" [Jim Smith(202)] AstNum=202 (Jim Smith) BstNum=201 (Mary Smith)

What I am trying to do is to parse out each section of the string and hopefully use it as an actual Variable.

That is, parse out say Stack=3 and use that as a variable named Stack with a value of 3 in my program.

In the past I have used the VB6 Split at each SPACE and put everything into an array. However, in this case there are spaces in the names, so that does not work for me.

I have also used Instr and Mid$ (in the past) to parse other strings similar to this but not quite the same.

It would be nice if there were a more elegant and efficient way to parse the string and preserve the names and values.

I have used Google for many years to find examples and lessons on other areas of VB6, but I just can't find anything that leads me to a solution for this.

Perhaps there is some type of "Sting to Variable" function/Method.

Thanks in advance....
 
hi,

Check out the Split() function.
Code:
dim a, i as integer, s as string

s = "Stack=3 Ask=1 Base=0.0 Ast="Mary Smith(201)" Bst="Jim Smith(202)" [Jim Smith(202)] AstNum=202 (Jim Smith) BstNum=201 (Mary Smith)"

a = split(s, " ")

for i = ubound(a) to ubound(a)
   debug.print a(i)
next

Skip,
[sub]
[glasses]Just traded in my OLD subtlety...
for a NUance![tongue][/sub]
 
Perhaps there is some type of "Sting to Variable" function/Method.
Not for anything that is as irregular as your example string.


You are going to need 'non-greedy' regular expression (RegExp) patterns to parse out the various keys and values because there is no real consistency to the value delimiters. The key names & the '=' sign will have to be the start of the match pattern with several combinations of delimiters for the end of the match.

Are all the incoming messages in exactly the same format, 'similar' is not precise enough to formulate a parsing algorithm from.

Are all lines terminated with the same character sequence such as a 0, NUL, CR, LF, CRLF or something else?

and that's without really thinking about solving the algorithm, :)




Chris.

Indifference will be the downfall of mankind, but who cares?
Time flies like an arrow, however, fruit flies like a banana.
Webmaster Forum
 
It would be nice to know what your "Sting to Variable" function/Method would do.

Do you want the outcome to be:[tt]
Stack=3
Ask=1
Base=0.0
Ast="Mary Smith(201)"
Bst="Jim Smith(202)" [Jim Smith(202)]
AstNum=202 (Jim Smith)
BstNum=201 (Mary Smith)[/tt]

Are you ALWAYS going to have these ‘pre-fixes’ so you can hard-code them:[tt]
Stack=
Ask=
Base=
Ast=
Bst=
AstNum=
BstNum=[/tt]

Could you give an example of how you would like "to parse the string and preserve the names and values."?

Have fun.

---- Andy
 
Sorry for the delayed response.
Last week was vacation time for me.

Anyway, Skip I tried the Split/Array approach initially and because of the spaces in the names it would not work for me.

Chris, I worked on this for awhile after reading your post and I was able to come up with Regular Expressions that would work every time.
(?<=…) Positive lookbehind assertion
Very smooth and easy to integrate into my code.
The problem I had is that I used a Regex Tool (Expresso 3.0) to develop the Regex that worked.

That was until I tried to use them with VB6.

It seems that the VB6 / VB Script Regular Expressions 5.5 that are available as a Reference, do not support the more complex Regex's that I made.

I looked on the Internet to see if there is/was any more advanced Regex above 5.5 or a replacement but did not find any.

That drove me back to an older method I have used whereby I use InString looking for the = (equal) signs and then using Mid$ to get to the next area desired.

I used the word "similar" to describe the string since the real string is very long, contained additional values but using the same structure and I was just looking for a parsing concept rather than an exact solution.



Andy, the example you gave as the outcome is what I wanted to do.

You asked: "Are you ALWAYS going to have these ‘pre-fixes’ so you can hard-code them:"

Yes, they will always be the same.


You also asked: "Could you give an example of how you would like "to parse the string and preserve the names and values."? "

One area that I parse out would be a string like Stack=3

Here is some Pseudo Code to explain it:
Then use something like Dim Stack=3 as Variable
Now Stack would be a variable (no longer a string) in my code, with a value of 3

I hope this helps to clear it up.

Thanks again.

 
Two more questions:
1. The 'desciptions': Stack, Ask, Base, ... - are they always going to be in the same order?
2. Are you always going to have ALL 'descriptions' every time?

Have fun.

---- Andy
 
Looks reasonably simple, and no need to even think about regular expressions.

If we assume you need to be able to retrieve both the Keys and the Values then you might hold them in a Dictionary, or just create a "KVPair" class and store instances of that in a Collection.

KVPair.cls
Code:
Option Explicit

Public Key As String
Public Value As String

Form1.frm
Code:
Option Explicit

Private Function KV2Collection(ByVal KVString As String) As Collection
    Dim Parts() As String
    Dim I As Long
    Dim Pos As Long
    Dim KV() As String
    Dim NewKV As KVPair

    Parts = Split(KVString, "=")
    For I = 0 To UBound(Parts) - 1
        Pos = InStrRev(Parts(I), " ")
        If Pos Then
            Mid$(Parts(I), Pos, 1) = vbFormFeed
        End If
    Next
    Parts = Split(Join$(Parts, "="), vbFormFeed)
    Set KV2Collection = New Collection
    For I = 0 To UBound(Parts)
        KV = Split(Parts(I), "=")
        Set NewKV = New KVPair
        NewKV.Key = KV(0)
        If UBound(KV) > 0 Then NewKV.Value = KV(1)
        KV2Collection.Add NewKV, NewKV.Key
    Next
End Function

Private Sub Command1_Click()
    Dim KVCollection As Collection
    Dim KV As KVPair
    
    Set KVCollection = KV2Collection(Text1.Text)
    Text2.Text = ""
    For Each KV In KVCollection
        Text2.Text = Text2.Text & KV.Key & " = " & KV.Value & vbNewLine
    Next
End Sub

If you don't need the Keys but only need to retrieve by Key, use a Collection and store the Value as a String (and forget about using any Class).

While we didn't get a clear description of the desired results, the example above produces:

Code:
Stack = 3
Ask = 1
Base = 0.0
Ast = "Mary Smith(201)"
Bst = "Jim Smith(202)" [Jim Smith(202)]
AstNum = 202 (Jim Smith)
BstNum = 201 (Mary Smith)
 
Here's a VB6 RegEx solution for the parsing part (assumes your text to be parsed is in a richtextbox):

Code:
[blue]    Dim re As RegExp
    
    Dim result As MatchCollection
    Dim myitem As Variant
    
    Set re = New RegExp
    
    With re
        .Pattern = "\b(\w*\=.*?)(?=\b\w*\=)|(\b\w*\=.*$)"
        .Global = True
        Set result = .Execute(RichTextBox1.Text)
    End With
    
    For Each myitem In result
        Debug.Print myitem
    Next[/blue]
 
Perhaps something along the lines of the following VBA code:
Code:
Sub Demo()
Dim Str As String, StrCut As String, i As Long, Arr As Variant
Str = "Stack=3 Ask=1 Base=0.0 Ast=""Mary Smith(201)"" Bst=""Jim Smith(202)"" [Jim Smith(202)] AstNum=202 (Jim Smith) BstNum=201 (Mary Smith)"
ReDim Arr(UBound(Split(Str, "=")))
Arr(0) = Split(Str, "=")(0)
For i = 1 To UBound(Arr)
  StrCut = Split(Arr(i - 1), " ")(UBound(Split(Arr(i - 1), " ")))
  Arr(i) = StrCut & "=" & Split(Str, "=")(i)
  Arr(i - 1) = Trim(Left(Arr(i - 1), Len(Arr(i - 1)) - Len(StrCut)))
Next
For i = 1 To UBound(Arr)
  MsgBox Arr(i)
Next
End Sub

Cheers
Paul Edstein
[MS MVP - Word]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top