如何在长文本中查找所有特定字符串

时间:2013-09-04 13:21:53

标签: vb.net string loops search

我在一个字符串和一行中有一些长文本(例如有关很多书的信息)。

我想找到只有ISBN(只有数字 - 每个数字都可以通过字符ISBN来防止)。我找到了代码如何在第一个位置提取这个数字。问题是如何为所有文本创建循环。我可以将它用于此示例流读取器吗?谢谢你的回答。

示例:

Sub Main()
    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    Dim test As Integer = getLiteratura.IndexOf("ISBN")
    Dim getISBN As String = getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5)

    Console.Write(getISBN)
    Console.ReadKey()
End Sub

3 个答案:

答案 0 :(得分:3)

由于您可以将起始位置传递到IndexOf方法,因此您可以通过从最后一次迭代停止的位置开始搜索来遍历字符串。例如:

Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
Dim isbns As New List(Of String)()
Dim position As Integer = 0
While position <> -1
    position = getLiteratura.IndexOf("ISBN", position)
    If position <> -1 Then
        Dim endPosition As Integer = getLiteratura.IndexOf(".", position + 1)
        If endPosition <> -1 Then
            isbns.Add(getLiteratura.Substring(position + 5, endPosition - position - 5))
        End If
        position = endPosition
    End If
End While

如果数据已经全部加载到字符串中,那么就像您可能找到的方法一样有效。但是,该方法不是非常易读或灵活。如果这些事情不只是关注效率,您可能需要考虑使用RegEx:

For Each i As Match In Regex.Matches(getLiteratura, "ISBN (?<isbn>.*?)\.")
    isbns.Add(i.Groups("isbn").Value)
Next

正如您所看到的,它不仅更容易阅读,而且还可以配置。您可以将模式外部存储在资源,配置文件,数据库等中。

如果数据尚未全部加载到字符串中,并且效率是最重要的考虑因素,您可能需要考虑使用流读取器,以便一次只将一小部分数据加载到内存中。这种逻辑会有点复杂,但仍然不会太困难。

以下是一个简单的示例,说明如何通过StreamReader

执行此操作
Dim isbns As New List(Of String)()
Using reader As StreamReader = New StreamReader(stream)
    Dim builder As New StringBuilder()
    Dim isbnRegEx As New Regex("ISBN (?<isbn>.*?)\.")
    While Not reader.EndOfStream
        Dim charValue As Integer = reader.Read()
        If charValue <> -1 Then
            builder.Append(Convert.ToChar(charValue))
            Dim matches As MatchCollection = isbnRegEx.Matches(builder.ToString())
            If matches.Count <> 0 Then
                For Each i As Match In matches
                    isbns.Add(i.Groups("isbn").Value)
                Next
                builder.Clear()
            End If
        End If
    End While
End Using

如您所见,在该示例中,只要找到匹配项,就会将其添加到列表中,然后清除用作缓冲区的builder。这样,一次在内存中保存的数据量永远不会超过一个“记录”的大小。

更新

因为根据您的评论,您无法正常使用它,所以这是一个完整的工作示例,它输出只是 ISBN编号,没有任何周围的字符。只需创建一个新的VB.NET控制台应用程序并粘贴以下代码:

Imports System.Text.RegularExpressions

Module Module1
    Public Sub Main()
        Dim data As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
        For Each i As String In GetIsbns(data)
            Console.WriteLine(i)
        Next
        Console.ReadKey()
    End Sub

    Public Function GetIsbns(data As String) As List(Of String)
        Dim isbns As New List(Of String)()
        For Each i As Match In Regex.Matches(data, "ISBN (?<isbn>.*?)\.")
            isbns.Add(i.Groups("isbn").Value)
        Next
        Return isbns
    End Function
End Module

答案 1 :(得分:0)

在处理大量数据时,我建议使用正则表达式。

尝试这样的事情:

    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    Dim Pattern As String = "ISBN (.*?)\."
    Dim ReturnedMatches As MatchCollection = Regex.Matches(getLiteratura, Pattern)
    For Each ReturnedMatch As Match In ReturnedMatches
        MsgBox(ReturnedMatch.Groups(1).ToString)
    Next

AND,在您的模块顶部,包含行Imports System.Text.RegularExpressions

希望这能指出你正确的方向......

答案 2 :(得分:0)

这是我的解决方案

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim outputtext As New String("")
    Dim test As Integer = 0
    Dim getLiteratura As String = "'Author 1. Name of book 1. ISBN 978-80-251-2025-5.', 'Author 2. Name of Book 2. ISBN 80-01-01346.', 'Author 3. Name of book. ISBN 80-85849-83.'"
    test = getLiteratura.IndexOf("ISBN")
    Dim getISBN As String = ""
    While Not getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5).Length = 0
        outputtext = outputtext & getLiteratura.Substring(test + 5, getLiteratura.IndexOf(".", test + 1) - test - 5) & " : "
        If getLiteratura.Substring(test + 1).IndexOf("ISBN") = 0 Then
            Exit While
        Else
            test = test + getLiteratura.Substring(test + 1).IndexOf("ISBN")
        End If
    End While

    Label1.Text = outputtext
End Sub