У меня есть много файлов с номерами версий в качестве последней части имени. Например:
Xxxxx V2.txt
Xxxxx V2.3.txt
Xxxxx V2.10.txt
Xxxxx V2.10.3.txt
Я использую Regex для извлечения частей номера версии, чтобы я мог правильно упорядочить файлы † и чтобы я мог рассчитать следующий номер версии ‡.
† Например: V2.2 предшествует V2.10, а V2.2 предшествует V2.2.3.
‡ Например: следующая версия после V2.9 - V2.10.
Я могу обрабатывать каждый стиль номера версии отдельно, но не могу обобщить, чтобы создать один шаблон Regex для всех стилей.
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 дал лучшие результаты, чем с моим неопрятным кодом. Мне придется пересмотреть мой оригинальный код, чтобы найти мою ошибку. С этим кодом выход для шаблона регулярного выражения 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», который является самым сложным стилем номера версии, который я когда-либо видел. Это не идеально, но это определенно улучшение моего текущего решения. Вы используете символы Regex, которые я не узнаю, поэтому мне нужно внимательно изучить это.
С помощью приведенного выше кода шаблон регулярного выражения 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"
===========================================
То есть всегда кажется, что он захватывает: первую часть, последнюю часть, включая точку, и последнюю часть без точки. Многообещающе, но не совсем.
Часть 3
Я пропустил запрос на четкое объяснение результата, который я ищу.
Я использую номера версий во всех моих важных файлах. Я получаю файлы от других, которые включают номера версий, некоторые из которых намного сложнее, чем у меня. У меня всегда есть номер версии в качестве последней части имени файла, и у меня всегда есть «V» перед номером версии. Если я получаю файлы, которые не соответствуют моему формату, я переименовываю их так, как они. Итак, у меня есть файлы с такими именами, как:
- Xxxxx VN.xxx
- Xxxxx VN.N.xxx
- Xxxxx VN.N.N.xxx
- Xxxxx VN.N.N.N.xxx
Я хочу извлечь Ns в массив переменной длины или коллекцию, чтобы я мог обработать их с помощью стандартных процедур. На самом деле, у меня уже есть эти общие процедуры. Эти процедуры основаны на некотором грязном коде VBA, который извлекает Ns. Я думал, что использование Regex позволит мне привести в порядок свой код.