Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 可以单独提取组的每个匹配项,但不能作为重复组提取_Regex_Excel_Vba - Fatal编程技术网

Regex 可以单独提取组的每个匹配项,但不能作为重复组提取

Regex 可以单独提取组的每个匹配项,但不能作为重复组提取,regex,excel,vba,Regex,Excel,Vba,我有许多文件,名称的最后一部分是版本号。例如: Xxxxx V2.txt Xxxxx V2.3.txt Xxxxx V2.10.txt Xxxxx V2.10.3.txt 我使用正则表达式提取部分版本号,以便正确排列文件†的顺序,并计算下一个版本号 †例如:V2.2排在V2.10之前,V2.2排在V2.2.3之前 ‡例如:V2.9之后的下一个版本是V2.10 我可以单独处理版本号的每个样式,但我不能概括为为所有样式创建一个正则表达式模式 Text Pattern

我有许多文件,名称的最后一部分是版本号。例如:

Xxxxx V2.txt
Xxxxx V2.3.txt
Xxxxx V2.10.txt
Xxxxx V2.10.3.txt
我使用正则表达式提取部分版本号,以便正确排列文件†的顺序,并计算下一个版本号

†例如:V2.2排在V2.10之前,V2.2排在V2.2.3之前

‡例如:V2.9之后的下一个版本是V2.10

我可以单独处理版本号的每个样式,但我不能概括为为所有样式创建一个正则表达式模式

Text               Pattern                          Value(s) extracted
Xxxxx V2.txt       Xxxxx V(\d+)\.txt                2
Xxxxx V2.3.txt     Xxxxx V(\d+)\.(\d+)\.txt         2  3
Xxxxx V2.10.3.txt  Xxxxx V(\d+)\.(\d+)\.(\d+)\.txt  2  10  3
Xxxxx V2.10.3.txt  Xxxxx V(\d+){\.(\d+)}*\.txt      No match
我不明白为什么最后一种模式不适用于所有版本号的样式。感谢您的指导

回应评论意见的新章节

我希望我的正则表达式模式中有一个简单的错误,我的代码与此无关。我整理了测试代码以创建:

Sub CtrlTestCapture()

  Dim Patterns As Variant
  Dim Texts As Variant

  Texts = Array("Xxxxx V12.txt", _
                "Xxxxx V12.3.txt", _
                "Xxxxx V12.4.5.txt", _
                "Xxxxx V12.4.5.3.txt")

  Patterns = Array("Xxxxx V(\d+)\.txt", _
                   "Xxxxx V(\d+)\.(\d+)\.txt", _
                   "Xxxxx V(\d+)\.(\d+)\.(\d+)\.txt", _
                   "Xxxxx V(\d+){\.(\d+)}+\.txt", _
                   "Xxxxx V(\d+)(?:\.(\d+))?(?:\.(\d+))?\.txt" , _
                   "Xxxxx V(\d+)(\.(\d+))*\.txt")

  Call TestCapture(Patterns, Texts)

End Sub
Sub TestCapture(ByRef Patterns As Variant, ByRef Texts As Variant)

  Dim InxM As Long
  Dim InxS As Long
  Dim Matches As MatchCollection
  Dim PatternCrnt As Variant
  Dim RegEx As New RegExp
  Dim SubMatchCrnt As Variant
  Dim TextCrnt As Variant

  With RegEx
    .Global = True         ' Find all matches
    .MultiLine = False     ' Match cannot extend across linebreak
    .IgnoreCase = True

    For Each PatternCrnt In Patterns
     .Pattern = PatternCrnt

      For Each TextCrnt In Texts
        Debug.Print "==========================================="
        Debug.Print "   Pattern: """ & PatternCrnt & """"
        Debug.Print "      Text: """ & TextCrnt & """"
        If Not .test(TextCrnt) Then
          Debug.Print Space(12) & "Text does not match pattern"
        Else
          Set Matches = .Execute(TextCrnt)
          If Matches.Count = 0 Then
            Debug.Print Space(12) & "Match but no captures"
          Else
            For InxM = 0 To Matches.Count - 1
              Debug.Print "-------------------------------------------"
              With Matches(InxM)
                Debug.Print "     Match: " & InxM + 1
                Debug.Print "     Value: """ & .Value & """"
                Debug.Print "    Length: " & .Length
                Debug.Print "FirstIndex: " & .FirstIndex
                For InxS = 0 To .SubMatches.Count - 1
                  Debug.Print "  SubMatch: " & InxS + 1 & " """ & .SubMatches(InxS) & """"
                Next
              End With
            Next
          End If
        End If
      Next
    Next
    Debug.Print "==========================================="

  End With

End Sub
有了这段代码,Wiktor Stribiżew regex模式产生的结果比我的不整洁代码要好。我将不得不检查我的原始代码以找到我的错误。使用此代码,Wiktor Stribiżew正则表达式模式的输出为:

===========================================
   Pattern: "Xxxxx V(\d+)(?:\.(\d+))?(?:\.(\d+))?\.txt"
      Text: "Xxxxx V12.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.txt"
    Length: 13
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 ""
  SubMatch: 3 ""
===========================================
   Pattern: "Xxxxx V(\d+)(?:\.(\d+))?(?:\.(\d+))?\.txt"
      Text: "Xxxxx V12.3.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.3.txt"
    Length: 15
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 "3"
  SubMatch: 3 ""
===========================================
   Pattern: "Xxxxx V(\d+)(?:\.(\d+))?(?:\.(\d+))?\.txt"
      Text: "Xxxxx V12.4.5.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.4.5.txt"
    Length: 17
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 "4"
  SubMatch: 3 "5"
===========================================
   Pattern: "Xxxxx V(\d+)(?:\.(\d+))?(?:\.(\d+))?\.txt"
      Text: "Xxxxx V12.4.5.3.txt"
            Text does not match pattern
===========================================
这有固定数量的捕获,而不是我尝试的可变数量。我还必须研究如何将其扩展到处理“12.4.5.3”,这是我见过的最复杂的版本号样式。这并不完美,但绝对是对我当前工作环境的改进。您使用的是我不认识的正则表达式字符,因此我需要仔细研究

使用上述代码,Tiw正则表达式模式生成以下输出:

===========================================
   Pattern: "Xxxxx V(\d+)(\.(\d+))*\.txt"
      Text: "Xxxxx V12.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.txt"
    Length: 13
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 ""
  SubMatch: 3 ""
===========================================
   Pattern: "Xxxxx V(\d+)(\.(\d+))*\.txt"
      Text: "Xxxxx V12.3.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.3.txt"
    Length: 15
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 ".3"
  SubMatch: 3 "3"
===========================================
   Pattern: "Xxxxx V(\d+)(\.(\d+))*\.txt"
      Text: "Xxxxx V12.4.5.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.4.5.txt"
    Length: 17
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 ".5"
  SubMatch: 3 "5"
===========================================
   Pattern: "Xxxxx V(\d+)(\.(\d+))*\.txt"
      Text: "Xxxxx V12.4.5.3.txt"
-------------------------------------------
     Match: 1
     Value: "Xxxxx V12.4.5.3.txt"
    Length: 19
FirstIndex: 0
  SubMatch: 1 "12"
  SubMatch: 2 ".3"
  SubMatch: 3 "3"
===========================================
也就是说,它似乎总是捕捉到:第一部分,最后一部分包括圆点,最后一部分没有圆点。很有希望,但不太可能

第三部分

我忽略了对我寻求的结果作出明确解释的要求

我在所有重要文件上使用版本号。我收到其他人的文件,其中包括版本号,其中一些比我的要复杂得多。我总是将版本号作为文件名的最后一部分,并且在版本号之前总是有一个“V”。如果我收到的文件不符合我的格式,我会重新命名它们。因此,我有一些文件的名称如下:

Xxxxx VN.xxx Xxxxx VN.N.xxx Xxxxx VN.N.N.xxx Xxxxx VN.N.N.xxx 我希望将Ns提取到可变长度数组或集合中,以便使用通用例程处理它们。事实上,我已经有了这些通用程序。这些例程依赖于提取Ns的一些凌乱的VBA代码。我认为使用正则表达式可以让我整理代码

试试这个正则表达式:

V(\d+(?:\.\d+)*)\.txt$
所需版本在组1中捕获。您可以使用一个字符串进一步拆分组1的内容

代码:

正则表达式解释:

V\d+?:\。\d+*\.txt$ V-匹配V \d+?:\。\d+*-匹配数字的1+次出现次数。在匹配尽可能多的数字后,匹配0个或更多出现的点。后跟1+个数字。整个匹配在第1组中捕获,并且是您所需的版本号 \.txt-matches.txt $-断言行的结尾。 试试这个正则表达式:

V(\d+(?:\.\d+)*)\.txt$
所需版本在组1中捕获。您可以使用一个字符串进一步拆分组1的内容

代码:

正则表达式解释:

V\d+?:\。\d+*\.txt$ V-匹配V \d+?:\。\d+*-匹配数字的1+次出现次数。在匹配尽可能多的数字后,匹配0个或更多出现的点。后跟1+个数字。整个匹配在第1组中捕获,并且是您所需的版本号 \.txt-matches.txt $-断言行的结尾。
如果您愿意,这里有一个非正则表达式的解决方案。您可以将版本号转换为数字,然后对其进行排序

Sub GetOrderedList()
    Dim Texts               As Variant
    Dim FileName            As String
    Dim FileArrayList       As Object
    Dim Item                As Variant

    Set FileArrayList = CreateObject("System.Collections.ArrayList")

    Texts = Array("Xxxxx V12.txt", _
                  "Xxxxx V12.3.txt", _
                  "Xxxxx V12.4.5.txt", _
                  "Xxxxx V12.4.5.3.txt")


    For i = LBound(Texts) To UBound(Texts)
        'You get use the FileSystemObject to make this a bit easier
        FileName = Replace(Replace(Split(Texts(i), " ")(UBound(Split(Texts(i), " "))), "V", ""), ".txt", "")
        PeriodPosition = InStr(1, FileName, ".")

        'Convert to a number, then sort
        If PeriodPosition > 0 Then FileName = Left$(FileName, PeriodPosition) & Replace(FileName, ".", "0", PeriodPosition + 1)
        FileArrayList.Add FileName
    Next

    'Sort
    FileArrayList.Sort

    'Print out, ascending order
    For Each Item In FileArrayList
        Debug.Print Item
    Next

End Sub

如果您愿意,这里有一个非正则表达式的解决方案。您可以将版本号转换为数字,然后对其进行排序

Sub GetOrderedList()
    Dim Texts               As Variant
    Dim FileName            As String
    Dim FileArrayList       As Object
    Dim Item                As Variant

    Set FileArrayList = CreateObject("System.Collections.ArrayList")

    Texts = Array("Xxxxx V12.txt", _
                  "Xxxxx V12.3.txt", _
                  "Xxxxx V12.4.5.txt", _
                  "Xxxxx V12.4.5.3.txt")


    For i = LBound(Texts) To UBound(Texts)
        'You get use the FileSystemObject to make this a bit easier
        FileName = Replace(Replace(Split(Texts(i), " ")(UBound(Split(Texts(i), " "))), "V", ""), ".txt", "")
        PeriodPosition = InStr(1, FileName, ".")

        'Convert to a number, then sort
        If PeriodPosition > 0 Then FileName = Left$(FileName, PeriodPosition) & Replace(FileName, ".", "0", PeriodPosition + 1)
        FileArrayList.Add FileName
    Next

    'Sort
    FileArrayList.Sort

    'Print out, ascending order
    For Each Item In FileArrayList
        Debug.Print Item
    Next

End Sub

如果需要一到三个部分,请使用V\d+?:\。\d+?:\。\d+?\.txt。在VBA正则表达式中,您无法访问组的所有捕获。@WiktorStribiżew感谢您的建议,但它对我不起作用。它为文本的每个字符返回一个匹配项,每个匹配项都是空字符串。您没有显示代码,也没有解释要获得的确切输出。如果你想让某些东西为你工作,你需要提供更多的细节。@WiktorStribiżew我已经整理了我的测试代码,你的模式现在提供了更好的结果。请看我问题的新部分。Tiv的一个建议似乎已经消失了。我问题中的新部分演示了该建议模式的输出。如果您希望使用一到三个部分,请使用V\d+?:\。\d+?:\。\d+?\.txt。在VBA正则表达式中,您无法访问组的所有捕获。@WiktorStribiżew感谢您的建议,但它对我不起作用。它为文本的每个字符返回一个匹配项,每个匹配项都是空字符串。您没有显示代码,也没有解释要获得的确切输出。如果你想为自己做点什么,y
您需要提供更多详细信息。@WiktorStribiżew我已经整理了测试代码,您的模式现在提供了更好的结果。请看我问题的新部分。Tiv的一个建议似乎已经消失了。我问题中的新部分演示了该建议模式的输出。@TonyDallimore这不是您要找的吗?很抱歉反应太慢。我试图对每一条评论做出正确的回应,并按顺序回答。这是我发现的第一个可行的建议。它将整个版本号提取为一个字符串,我可以很容易地用Split进行分割。我想分别捕获版本号的每个部分,但是捕获整个版本号可能更方便+一个有效的答案。检查完所有其他建议后,我将接受。其他建议已被删除,因此您没有竞争对手。这不是我所寻求的答案,但比我所寻求的答案更好。我记得当我支持的时候,我会收到一些关于一些模糊技术的问题。经过多次询问,我发现他们的实际需求非常简单,但他们已经决定采用晦涩难懂的技术作为解决方案。很高兴该解决方案对您有所帮助:@TonyDallimore这不是您想要的吗?很抱歉反应太慢。我试图对每一条评论做出正确的回应,并按顺序回答。这是我发现的第一个可行的建议。它将整个版本号提取为一个字符串,我可以很容易地用Split进行分割。我想分别捕获版本号的每个部分,但是捕获整个版本号可能更方便+一个有效的答案。检查完所有其他建议后,我将接受。其他建议已被删除,因此您没有竞争对手。这不是我所寻求的答案,但比我所寻求的答案更好。我记得当我支持的时候,我会收到一些关于一些模糊技术的问题。经过多次询问,我发现他们的实际需求非常简单,但他们已经决定采用晦涩难懂的技术作为解决方案。很高兴该解决方案对您有所帮助:感谢您的回答,其中包括一些有趣的想法。它确实对FileArrayList进行了正确排序,但这只是我的一个用例。目前,我不知道如何开发这种方法来处理我的所有用例。但是,对于有趣的想法,+1。谢谢你的答案,其中包括一些有趣的想法。它确实对FileArrayList进行了正确排序,但这只是我的一个用例。目前,我不知道如何开发这种方法来处理我的所有用例。然而,有趣的想法是+1。