【问题标题】:How to find all occurrences of specific string in long text如何在长文本中查找所有出现的特定字符串
【发布时间】:2013-09-04 13:21:53
【问题描述】:

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

我只想找到 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

【问题讨论】:

    标签: vb.net string loops search


    【解决方案1】:

    由于您可以将开始位置传递给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。这样,一次保存在内存中的数据量永远不会超过一个“记录”的大小。

    更新

    由于根据您的 cmets,您无法使其正常工作,这里有一个完整的工作示例,它输出 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
    

    【讨论】:

    • 这很棒,而且使用 RegEx 也很简单。谢谢你。我对列表中的每个项目都有另一个问题。无论如何都可以修改这个项目吗?我想只有数字(没有 ISBN 字符和没有 .)。我可以使用类似子字符串的东西吗?
    • 我实际上已经在前几天解决了这个问题,就在我回答问题后不久。我注意到 RegEx 模式在结果中包含了这些内容。所以我怀疑你使用的代码是在我修复我的答案中的模式之前。我已将其从 "(?&lt;isbn&gt;ISBN .*?\.)" 更改为 "ISBN (?&lt;isbn&gt;.*?)\."
    • 很抱歉,但这仍然不起作用。项目中还有 ISNB 和点。我知道,我必须更改表达式中的某些内容,但我不知道如何制作 RegExp。
    • 我更新了我的答案以包含一个完整的工作示例。尽管 RegEx 很棒,但它可能会让人感到困惑,尤其是对于刚接触它的人来说。我从不建议任何人使用他们自己不完全理解的任何东西。它是否有效并不重要。如果你不明白为什么它会起作用,那就像它根本不起作用一样可怕。如果你没有时间学习 RegEx,那就坚持你觉得舒服的东西。如果您有时间,值得投资学习它,这样您就会感到舒适。
    【解决方案2】:

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

    试试这样的:

        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
    

    并且,在你的模块顶部,包含Imports System.Text.RegularExpressions这一行

    希望这会为您指明正确的方向...

    【讨论】:

      【解决方案3】:

      这是我的解决方案

      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
      

      【讨论】:

        猜你喜欢
        • 2012-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-21
        • 1970-01-01
        • 2012-10-12
        • 1970-01-01
        相关资源
        最近更新 更多