gpt4 book ai didi

regex - 在双正斜杠和/或使用 RegExp 的特定单词上拆分字符串

转载 作者:行者123 更新时间:2023-12-04 22:02:03 24 4
gpt4 key购买 nike

我正在尝试通过双正斜杠和/或特定字符串(例如“and”)来拆分文本。

Example A:
text1 a/s // text2 a/b
text1 a/s and text2 a/b


Example B:
text1. // text2,// text3-
text1. and text2, and text3-
  • 示例 A 返回两个匹配项: text1 a/s text2 a/b
  • 示例 B 返回三个匹配项:text1。文本2,文本3-

  • 我得到了非常有用的提示如何用单个正斜杠分割:
    Split string on single forward slashes with RegExp ,但试图找到一个解决方案来排除两个正斜杠或一个字符串,被证明太具有挑战性了。

    如果可以为两个示例组合一个解决方案,则可以加分:
    Example C:
    text1 a/s // text2, and text3-

    我只希望与 VBA 兼容的 RegExp 解决方案。

    最佳答案

    正如您所说,您已经为 Split string on single forward slashes with RegExp 中的不同拆分字符提供了可行的解决方案。 .该代码实际上并未拆分字符串,但它匹配除“/ ”之外的所有内容。然后它在 collection 中返回每个单独匹配的结果。 (是的,它最终 split )。

    你需要做的是匹配str中的每个字符, 除非下一个字符是 //and .我们可以使用 lookahead为了这。

    只需使用以下代码更改代码中的模式:

    .Pattern = "(?!$)((?:(?!//|\band\b).)*)(?://|and|$)"

    或者,如果要修剪每个标记的空格,请使用以下正则表达式:

    .Pattern = "(?!$)((?:(?!\s*//|\s*\band\b).)*)\s*(?://|and|$)\s*"

    虽然这也将匹配 //and ,它使用 ( group ) 捕获实际的 token 。因此,您必须使用 .SubMatches(0) 将 token 添加到集合中。 (第一组反向引用的内容)。

    在您的代码中,而不是添加 coll.Add r_item.Value , 利用:

    coll.Add r_item.SubMatches(0)

    注意:如果你的字符串有换行符,别忘了设置 rExp带有 .Multiline = True 的对象.

    VBA代码:

    Sub GetMatches(ByRef str As String, ByRef coll As Collection)

    Dim rExp As Object, rMatch As Object

    Set rExp = CreateObject("vbscript.regexp")
    With rExp
    .Global = True
    .MultiLine = True
    .Pattern = "(?!$)((?:(?!\s*//|\s*\band\b).)*)\s*(?://|and|$)\s*"
    End With

    Set rMatch = rExp.Execute(str)
    If rMatch.Count > 0 Then
    For Each r_item In rMatch
    coll.Add r_item.subMatches(0)
    Next r_item
    End If
    End Sub

    这就是您可以使用示例调用它的方式:

    Dim text As String
    text = "t/xt1.//text2,and landslide/ andy // text3- and text4"

    'vars to get result of RegExp
    Dim matches As New Collection, token
    Set matches = New Collection

    'Exec the RegExp --> Populate matches
    GetMatches text, matches

    'Print each token in debug window
    For Each token In matches
    Debug.Print "'" & token & "'"
    Next token
    Debug.Print "======="

    每个 token 都打印在即时窗口中。
  • 此代码是 @stribizhev 最初发布的代码的修改版本

  • 立即窗口中的输出:

    't/xt1.'
    'text2,'
    'landslide/ andy'
    'text3-'
    'text4'
    =======

    更深入的解释

    您可能想知道这种模式是如何工作的。我会尝试用详细的描述来解释。为此,让我们仅使用模式的重要部分,使用以下正则表达式(其余部分并不重要):
    ((?:(?!//|\band\b).)*)(?://|and|$)

    它可以很容易地分为两种结构:
  • 一、子模式((?:(?!//|\band\b).)*)group匹配每个标记,反向引用我们要为每个匹配返回的文本。在 ,组返回 .SubMatches() .让我们停下来:
  • 内部表达式(?!//|\band\b).首先检查以确保它后面没有拆分字符串(“//”或“and”)。如果不是,则正则表达式引擎匹配 一个 字符(注意末尾的点)。就是这样,它匹配我们捕获的 token 中允许的一个字符。
  • 现在,它包含在 (?:(?!//|\band\b).)* 中为了对它可以匹配的每个字符重复它,我们得到了 token 中的所有字符。这个结构是最接近 while loop 的结构。 .

    While it's not followed by a split string, get next char.

  • 如果你仔细想想,它是构造 .*我们都知道,每个字符都有一个额外的条件。
  • 第二个子模式(?://|and|$)更简单,只需匹配一个拆分字符串(“//”、“and”或行尾)。它在 non-capturing group 内,这意味着它将被匹配,但它不会存储其值的副本。

  • 例如:
    text1 a/s and text2 a/b//last
    ^ ^| | [1]: 1st subpattern, captured in Matches(0).SubMatches(0)
    |--------|^-^
    | 1 2| [2]: Split string, not captured but included in match
    |-----------|
    3 [3]: The whole match, returned by Matches(0)


    For the second match, Matches(1).Value = " text2 a/b//"
    Matches(1).Submatches(0) = " text2 a/b"

    该模式的其余部分只是细节:
  • (?!$)是为了避免在行尾匹配一个空字符串。
  • 所有\s*是否可以修剪 token (以避免在 token 的开头或结尾捕获空格)。
  • 关于regex - 在双正斜杠和/或使用 RegExp 的特定单词上拆分字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32633494/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com