I am writing a program that has to read a text file for a string that is surrounded by [ ]. I then want to grab the text behind it which is surrounded by ( ). The string i want to grab is in the same line as the one i searched for. So far i have been able to read the file and i looked everywhere for a solution on how to get the string but none of them worked. Please help me.

An example of the text file i'm searching for would be:
[String i'm searching for] (what i would like to grab from the text file)
[String i'm searching for] (what i would like to grab from the text file)
[String i'm searching for] (what i would like to grab from the text file)
There would be multiple lines in the text file.

You can read the entire file into a string array as

Dim allLines() As String = System.IO.File.ReadAllLines(MYFILE)

and you can extract the "interesting" lines as

Dim myLines() As String = Filter(allLines,"[String I'm searching for]")

The array, myLines, will contain only the lines from allLines containing the given string. Filter takes two additional (optional) parameters. Parameter 3, if given, is a boolean value. If True then all lines containing the string are returned. If False then all lines NOT containing the string are returned. Parameter 4 can be either CompareMethod.Text (case insensitive) or CompareMethod.Binary (case sensitive).

Once you have a matching line you can get the part you want either by

line.Substring(InStr(line,"(")-1)

or

Trim(line.Split("]")(1))

The first version will fail if there is no text following the matched string. The second version will correctly return a zero-length string.

I have one question...

Dim allLines() As String = System.IO.File.ReadAllLines(filepath)

works fine. I can put the array in a rich text box by line.
but...

Dim myLines() As String = Filter(allLines,"[String I'm searching for]")

When I search the array and try to display a messagebox of the string it gives me the error

Value of type '1-dimensional array of String' cannot be converted to 'String'

I am also a little confused about

line.Substring(InStr(line,"(")-1)

and

Trim(line.Split("]")(1))

When I type the code in it gives my the error...

'Line' statements are no longer supported. File I/O functionality is available as 'Microsoft.VisualBasic.FileSystem.LineInput' and the graphics functionality is available as 'System.Drawing.Graphics.DrawLine'

I started programming in early March and do not know much about arrays. I thank you for trying but could you explain it a bit more.

Another thing I forgot my text file doesn't contain any of the same strings between the [ ] 's.

I just used "line" as a generic string variable.

For Each line As String in myLines
    MsgBox(Trim(line.Split("]")(1)))
Next

Would display the requested text from each matching line.

line.Split("]")

splits the line into two strings using "]" as the delimiter

line.Split("]")(1)

takes the second element of the resulting array and

Trim(line.Split("]")(1))

removes leading and trailing blanks.

Edited 4 Years Ago by Reverend Jim

And if each line is different then

For Each line As String In System.IO.File.ReadAllLines("d:\temp\test.txt")

    Dim lb As Integer = InStr(line, "[")
    Dim rb As Integer = InStr(line, "]")

    'make sure line has "[" followed by "]"

    If lb > 0 And rb > 0 And rb > lb Then
        MsgBox(Trim(line.Substring(rb)))
    End If

Next

And you can use your method of choice to get at the text following the "]"

I still have a problem. I can get the strings between the ( )'s but It shows all of them in my text file. I do not know how to implement the search.

For Each line As String In System.IO.File.ReadAllLines("d:\temp\test.txt")

`Dim lb As Integer = InStr(line, "[")`
`Dim rb As Integer = InStr(line, "]")`


`'make sure line has "[" followed by "]"`


`If lb > 0 And rb > 0 And rb > lb Then`

    `MsgBox(Trim(line.Substring(rb)))`

`End If`

Next

This got me the string like I said.

But these didn't work

For Each line As String in myLines

`MsgBox(Trim(line.Split("]")(1)))`

Next

line.Split("]")

line.Split("]")(1)

Trim(line.Split("]")(1))

Because my code that searches the array:

Dim myLines() As String = Filter(allLines, "[" + Q + "]", True, CompareMethod.Text)

Does not work. Q is my string I am searching for.

When I used to work for a living I would get requests from my users to write programs or to modify existing ones. My usual first response was to write up, in my own terms, what it was I thought they were asking for. I would ask them to either confirm or clarify based on my description. I found this was less time consuming in the long run than asking a lot of questions. So let me try that here. This what I think you want to do:

You have a file containing lines of text. Some (maybe just one, perhaps many) lines consist of a string enclosed in square brackets followed by a string in parentheses. You want to process all lines in the file. For each line starting with

[some arbitrary text]

You want to extract the text between the "(" and ")" on the same line. I'm going to suggest a method that is different from the previous suggestions but will be more robust. It involves the use of regular expressions. If you are unfamiliar with regular expressions, in the simplest sense, they are a way of describing a pattern. It may sound complicated at first but for what you want to do it is fairly simple. In your case, the pattern in English would be

A left square bracket followed by an arbitrary number of characters followed by a right square bracket followed by an arbitrary number of characters followed by a left parenthesis followed by an arbitrary number of characters followed by a right parenthesis. Just like in VB, regular expressions have some characters with special meaning. In order to "escape" the special meaning we have to put a "\" in front of the special characters. To match a left square bracket (special char) we use "[". A decimal matches any character and an asterisk says "any number of them". So "." matches any number of characters. To match a variable length string in square brackets we use the pattern "[.]". Two more quickies - "^" matches the start of a line and "$" matches the end. Based on that the code becomes:

Imports System.Text.RegularExpressions

Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Dim pattern As String = "^\[.*\].*\(.*\).*"     'matches "[any text] any text (any text)"
        Dim parenth As String = "\(.*\)"                'matches "(any text)"

        For Each line As String In System.IO.File.ReadAllLines("d:\temp\test.txt")

            If Regex.IsMatch(line, pattern) Then
                line = line.Split("]")(1)
                Dim match As String = Regex.Match(line, parenth).Value
                match = match.Substring(1, Len(match) - 2)
                TextBox1.AppendText(match & vbCrLf)
            End If

        Next

    End Sub

End Class

And to finish up...

Regex.IsMatch(line, pattern) 

checks if the current line contains the pattern.

line = line.Split("[")(1)

gets rid of everything up to and including the closing "]". We need to do this in case the string between "[" and "]" contains a "(".

Regex.Match(line, parenth).Value

returns the string matched by the pattern we created for "(any text)"

match = match.Substring(1, Len(match) - 2)

lops off the "(" and ")" at the start and end

Edited 4 Years Ago by Reverend Jim

I avoided the use of regular expressions in my original answer because they can be a bit off-putting to people unfamiliar with the concept.

I tried that and everything went well. It gave me the strings inbetween the ( )'s but it gave me every single one in the text file. I'm not sure how to fix this because like you said I am unfamiliar with the concept.

In that case I misunderstand what it is you are trying to do. Perhaps if you posted a sample input file and told me explicitly what strings you are trying to extract.

[String to search can be any length and has spaces.] (String I wish to grab, any length spaces as well.)

[String could be a single word.] (String I wish to grab could be a single word.)

[String to search can be any length and has spaces.] (String I wish to grab, any length spaces as well.)

[String could be a single word.] (String I wish to grab could be a single word.) etc...

I am using the text file as a "database" for my program. So the program searches the text file for a string that a
user imputs and then it returns a value as a string. It is kind of like a dictionary but that is not what I'm using this for. I cannot put this into the code of the program because I don't think you can change it and the text file could have X ammount of lines. If you know an easier way to do this that could help.

I just noticed a horrible typo in my regex sample. The Split should have read

line = line.Split("]")(1)

My originial post (which I have since corrected) split on "[".

If the values between "[" and "]" are unique within the file then you can use a dictionary as

    Dim settings As New Dictionary(Of String, String)

    Dim parenth As String = "\(.*\)"                'matches "(any text)"
    Dim pattern As String = "^\[.*\].*\(.*\).*"     'matches "[any text] any text (any text)"

    For Each line As String In System.IO.File.ReadAllLines("d:\temp\test.txt")

        If Regex.IsMatch(line, pattern) Then

            'split on closing square bracket

            Dim flds() As String = line.Split("]")

            'get text between "[" and "]"

            Dim key As String = flds(0).Substring(1)

            'get text between "(" and ")"

            Dim val As String = Regex.Match(flds(1), parenth).Value
            val = val.Substring(1, Len(val) - 2)

            settings.Add(key, val)

        End If

    Next

    For Each key As String In settings.Keys
        TextBox1.AppendText(key & " = " & settings(key) & vbCrLf)
    Next

And this time I tested the code for typos. Of course, you would declare the dictionary at the class level otherwise it would exist only within the given sub or function. To get the value of any of the entries yopu would index the dictionary like and array but use the string from [mystring] as the index as in

Dim item As String = settings("some string")

Edited 4 Years Ago by Reverend Jim

In that case the dictionary code above should do the trick. You'll only have to process the text file once to get the [] and () key-value pairs into the dictionary. Sorry for the earlier typo.

Where do I implement the search in the above dictionary code? When I tried it without the search the results in the text box read:

apple. = a fruit.
carrot. = a vegitable.
string. = a phrase or text.

My text file read:

[apple.] (a fruit.)
[carrot.] (a vegitable.)
[string.] (a phrase or text.)

I would like to search for "apple" (when I search I would include the [ ] 's and "." programmatically) and then in the text box I would see "a fruit." This would also happen if I searched for "carrot" it would say "a vegitable."

These are just examples. In the real text file there would be multiple words per string and again they would all be unique. But the string between the ( )'s could also be within the [ ] 's. For example:

[apple.] (a fruit.)
[carrot.] (a vegitable.)
[string.] (a phrase or text.)
[a fruit.] (an example of a fruit would be an apple.)

So it can go both ways.

You don't have to search a dictionary. If you want the string corresponding to "apple" just do

Dim result As String = settings("apple")

result will end up with the value "a fruit" and

Dim nextresult As String = settings(settings("apple"))

will set nextresult to "an example of a fruit would be an apple"

This is my mistake. Sorry for my lack of knowledge on this topic but I have one last question. I think I am misusing the code you gave me...

Dim settings As New Dictionary(Of String, String)
        Dim parenth As String = "\(.*\)"                'matches "(any text)"
        Dim pattern As String = "^\[.*\].*\(.*\).*"     'matches "[any text] any text (any text)"
        For Each line As String In System.IO.File.ReadAllLines(filepath)
            If Regex.IsMatch(line, pattern) Then
                'split on closing square bracket
                Dim flds() As String = line.Split("]")
                'get text between "[" and "]"
                Dim key As String = flds(0).Substring(1)
                'get text between "(" and ")"
                Dim val As String = Regex.Match(flds(1), parenth).Value
                val = val.Substring(1, Len(val) - 2)
                settings.Add(key, val)
            End If
        Next
        For Each key As String In settings.Keys
            TextBox1.AppendText(key & " = " & settings(key) & vbCrLf)
            Dim result As String = settings(Q)
            TextBox1.Text = result
        Next

So when I run this through ( Q is the string I'm searching for) I typed in "apple" and got this error:

A first chance exception of type 'System.Collections.Generic.KeyNotFoundException' occurred in mscorlib.dll

It also says:
The given key was not present in the dictionary.

When the error occurs textbox1 says "apple = a fruit" i'm not sure if the error stopped the process but I wish for textbox1 to say "a fruit".

I can see one problem. The strings in your example all end in ".". Therefore, the key, "apple.", exists in the dictionary, but the key, "apple", does not. I should also point out that the keys are case sensitive. Thus, settings("apple") and settings("APPLE") refer to two different values. To see if a particular key exists you can use the ContainsKey method as in

If settings.ContainsKey("apple") Then
    'do something
Else
    'do somethinig else
End If

One way to prevent problems with case sensitivity is to force all keys to lower (or upper) case before adding them to the dictionary. The, when you check if a key exists, do the same in the test as in

If settings.ContainsKey(LCase(TextBox1.Text)) Then

Sorry again. The error was not of your code but of my ignorence. My database file was set up [apple] (a fruit). But it is supposed to be [apple.] (a fruit.). I'm sorry once more if I caused any trouble. This thread is resolved.

This question has already been answered. Start a new discussion instead.