egex语法:“(?组内容)”。 '组名可能包含以下字符:a-z、a-z、uz(下划线)。 '组名不能是空字符串。 '-options:可能包含以下内容的字符串: “-”i“(正则表达式不区分大小写) “-”g“(正则表达式将在全球范围内工作) “-”m“(正则表达式将在多行模式下工作) 或者这些的任意组合。 '返回值:包含以下项的脚本.Dictionary对象: '-项目0或“0”、1或“1”。。。对于组内容/子匹配, '遵循VBScript_RegExp_55.SubMatches集合的约定,该集合基于0。 “-项目匹配。假设组数低于,则整个匹配计数为-2或“98”。 “-项匹配。组/子匹配数的计数为-1或“99”。 '与原始版本相比的更改: “-处理非捕获组以及正向和反向前瞻组。 '-处理字符类内的左括号。 “-命名组不会计数两次。 '例如,在原始版本中,第二个命名组占用了返回文件的第3项和第4项 '字典,在此修订版本中,仅项目1(项目0是第一个命名组)。 “-附加的“m”选项。 “-修复了获取缓存正则表达式的问题。 “-早期绑定。 “-一些代码清理。 '例如,请查看上面的'TestRegexMatch'过程。 函数RegexMatch(ByVal haystack作为字符串,ByVal originalPattern作为字符串,可选ByVal选项作为字符串)作为脚本。字典 Dim GroupsPattern作为字符串 以字符串形式显示模式 Dim RealRegExp作为VBScript\u RegExp\u 55.RegExp Dim RealMatches作为VBScript\u RegExp\u 55.MatchCollection 将返回的数据设置为脚本.Dictionary 将组名设置为VBScript\u RegExp\u 55.MatchCollection 作为整数的Dim Ctr '缓存正则表达式和组名以进行优化。 作为脚本的静态CachedRegExps.Dictionary 静态CachedGroupNames作为脚本.Dictionary 'Group'meta'-regex用于检测命名和未命名的捕获组。 静态组RegExp作为VBScript\u RegExp\u 55.RegExp 如果CachedRegExps为Nothing,则设置CachedRegExps=New Scripting.Dictionary 如果CachedGroupNames为Nothing,则设置CachedGroupNames=New Scripting.Dictionary 如果GroupsRegExp什么都不是,那么 Set GroupsRegExp=New VBScript\u RegExp\u 55.RegExp '原始版本:GroupsRegExp.Pattern=“\((?:\?\)?” GroupsRegExp.Pattern=“\((?!(?:\?:\?:\?=?![^\]\[]*?\]))(?:\?)?” GroupsRegExp.Global=True 如果结束 '如果模式未缓存,请创建它。 如果不存在CachedRegExps.Exists((“&options&”&originalPattern),则 '准备检索命名组和未命名组的模式。 GroupsPattern=Replace(Replace(Replace)(Replace(原始模式,“\\”,“X”),“\(,“X”),“\[”,“X”),“X”) '存储组名称以进行优化。 CachedGroupNames.Add“(&options&”)和originalPattern,GroupsRegExp.Execute(groupspatern) '创建新的VBScript正则表达式有效模式并为此模式设置正则表达式。 RealPattern=GroupsRegExp.Replace(原始模式)(“”) Set RealRegExp=New VBScript\u RegExp\u 55.RegExp RealRegExp.Pattern=RealPattern '设置正则表达式选项。 对于Ctr=1至Len(选项) 选择案例中间(选项,中心,1) 案例“i” RealRegExp.IgnoreCase=True 案例“g” RealRegExp.Global=True 案例“m” RealRegExp.MultiLine=True 结束选择 下一个 '存储此正则表达式以进行优化。 cachedregxps.Add“(&options&”)和originalPattern,RealRegExp 如果结束 “拿火柴。 设置RealMatches=cachedregxps.Item(“(&options&”)和originalPattern.Execute(haystack) '获取组名。 Set GroupNames=CachedGroupNames.Item(“(&options&”)和originalPattern) '创建要返回的字典。 Set ReturnData=New Scripting.Dictionary '按照介绍此过程的备注中的说明,用名称和索引填充字典。 对于Ctr=1到GroupName.Count 如果为空(组名(Ctr-1).SubMatches(0)),则 返回数据。添加CStr(Ctr-1),RealMatches(0)。子匹配(Ctr-1) 其他的 ReturnData.添加组名(Ctr-1).子匹配(0),实匹配(0).子匹配(Ctr-1) 如果结束 下一个 ReturnData.Add“98”,RealMatches.Item(0) 返回数据。添加“99”,组名。计数 '返回结果。 Set RegexMatch=ReturnData 端函数
为了进一步改进,此代码可以作为替换VBScript regex的类模块的基础。在VBA中使用regexp时,通常是这样的:我认为它不支持命名组请显示您拥有的字符串示例。谢谢。如果用户能够用命名组传递自己的模式字符串,问题就解决了. :)egex语法:“(?组内容)”。 '组名可能包含以下字符:a-z、a-z、uz(下划线)。 '组名不能是空字符串。 '-options:可能包含以下内容的字符串: “-”i“(正则表达式不区分大小写) “-”g“(正则表达式将在全球范围内工作) “-”m“(正则表达式将在多行模式下工作) 或者这些的任意组合。 '返回值:包含以下项的脚本.Dictionary对象: '-项目0或“0”、1或“1”。。。对于组内容/子匹配, '遵循VBScript_RegExp_55.SubMatches集合的约定,该集合基于0。 “-项目匹配。假设组数低于,则整个匹配计数为-2或“98”。 “-项匹配。组/子匹配数的计数为-1或“99”。 '与原始版本相比的更改: “-处理非捕获组以及正向和反向前瞻组。 '-处理字符类内的左括号。 “-命名组不会计数两次。 '例如,在原始版本中,第二个命名组占用了返回文件的第3项和第4项 '字典,在此修订版本中,仅项目1(项目0是第一个命名组)。 “-附加的“m”选项。 “-修复了获取缓存正则表达式的问题。 “-早期绑定。 “-一些代码清理。 '例如,请查看上面的'TestRegexMatch'过程。 函数RegexMatch(ByVal haystack作为字符串,ByVal originalPattern作为字符串,可选ByVal选项作为字符串)作为脚本。字典 Dim GroupsPattern作为字符串 以字符串形式显示模式 Dim RealRegExp作为VBScript\u RegExp\u 55.RegExp Dim RealMatches作为VBScript\u RegExp\u 55.MatchCollection 将返回的数据设置为脚本.Dictionary 将组名设置为VBScript\u RegExp\u 55.MatchCollection 作为整数的Dim Ctr '缓存正则表达式和组名以进行优化。 作为脚本的静态CachedRegExps.Dictionary 静态CachedGroupNames作为脚本.Dictionary 'Group'meta'-regex用于检测命名和未命名的捕获组。 静态组RegExp作为VBScript\u RegExp\u 55.RegExp 如果CachedRegExps为Nothing,则设置CachedRegExps=New Scripting.Dictionary 如果CachedGroupNames为Nothing,则设置CachedGroupNames=New Scripting.Dictionary 如果GroupsRegExp什么都不是,那么 Set GroupsRegExp=New VBScript\u RegExp\u 55.RegExp '原始版本:GroupsRegExp.Pattern=“\((?:\?\)?” GroupsRegExp.Pattern=“\((?!(?:\?:\?:\?=?![^\]\[]*?\]))(?:\?)?” GroupsRegExp.Global=True 如果结束 '如果模式未缓存,请创建它。 如果不存在CachedRegExps.Exists((“&options&”&originalPattern),则 '准备检索命名组和未命名组的模式。 GroupsPattern=Replace(Replace(Replace)(Replace(原始模式,“\\”,“X”),“\(,“X”),“\[”,“X”),“X”) '存储组名称以进行优化。 CachedGroupNames.Add“(&options&”)和originalPattern,GroupsRegExp.Execute(groupspatern) '创建新的VBScript正则表达式有效模式并为此模式设置正则表达式。 RealPattern=GroupsRegExp.Replace(原始模式)(“”) Set RealRegExp=New VBScript\u RegExp\u 55.RegExp RealRegExp.Pattern=RealPattern '设置正则表达式选项。 对于Ctr=1至Len(选项) 选择案例中间(选项,中心,1) 案例“i” RealRegExp.IgnoreCase=True 案例“g” RealRegExp.Global=True 案例“m” RealRegExp.MultiLine=True 结束选择 下一个 '存储此正则表达式以进行优化。 cachedregxps.Add“(&options&”)和originalPattern,RealRegExp 如果结束 “拿火柴。 设置RealMatches=cachedregxps.Item(“(&options&”)和originalPattern.Execute(haystack) '获取组名。 Set GroupNames=CachedGroupNames.Item(“(&options&”)和originalPattern) '创建要返回的字典。 Set ReturnData=New Scripting.Dictionary '按照介绍此过程的备注中的说明,用名称和索引填充字典。 对于Ctr=1到GroupName.Count 如果为空(组名(Ctr-1).SubMatches(0)),则 返回数据。添加CStr(Ctr-1),RealMatches(0)。子匹配(Ctr-1) 其他的 ReturnData.添加组名(Ctr-1).子匹配(0),实匹配(0).子匹配(Ctr-1) 如果结束 下一个 ReturnData.Add“98”,RealMatches.Item(0) 返回数据。添加“99”,组名。计数 '返回结果。 Set RegexMatch=ReturnData 端函数,regex,vba,excel,Regex,Vba,Excel,为了进一步改进,此代码可以作为替换VBScript regex的类模块的基础。在VBA中使用regexp时,通常是这样的:我认为它不支持命名组请显示您拥有的字符串示例。谢谢。如果用户能够用命名组传递自己的模式字符串,问题就解决了. :) (?:<month>\d\d)(?:<day>\d\d) 'Description: ' An implementation of Regex which includes Named Groups ' and caching imp
(?:<month>\d\d)(?:<day>\d\d)
'Description:
' An implementation of Regex which includes Named Groups
' and caching implemented in VBA
'Example:
' Dim match as Object
' set match = RegexMatch("01/01/2019","(?<month>\d\d)\/(?<day>\d\d)\/(?<year>\d\d\d\d)")
' debug.print match("day") & "/" & match("month") & "/" & match("year")
'Options:
' "i" = IgnoreCase
'Return value:
' A dictionary object with the following keys:
' 0 = Whole match
' 1,2,3,... = Submatch 1,2,3,...
' "Count" stores the count of matches
' "<<NAME>>" stores the match of a specified name
Function RegexMatch(ByVal haystack As String, ByVal pattern As String, Optional ByVal options As String) As Object
'Cache regexes for optimisation
Static CachedRegex As Object
Static CachedNames As Object
If CachedRegex Is Nothing Then Set CachedRegex = CreateObject("Scripting.Dictionary")
If CachedNames Is Nothing Then Set CachedNames = CreateObject("Scripting.Dictionary")
'Named regexp used to detect capturing groups and named capturing groups
Static NamedRegexp As Object
If NamedRegexp Is Nothing Then
Set NamedRegexp = CreateObject("VBScript.RegExp")
NamedRegexp.pattern = "\((?:\?\<(.*?)\>)?"
NamedRegexp.Global = True
End If
'If cached pattern doesn't exist, create it
If Not CachedRegex(pattern) Then
'Create names/capture group object
Dim testPattern As String, oNames As Object
testPattern = pattern
testPattern = Replace(testPattern, "\\", "asdasd")
testPattern = Replace(testPattern, "\(", "asdasd")
'Store names for optimisation
Set CachedNames(options & ")" & pattern) = NamedRegexp.Execute(testPattern)
'Create new VBA valid pattern
Dim newPattern As String
newPattern = NamedRegexp.Replace(pattern, "(")
'Create regexp from new pattern
Dim oRegexp As Object
Set oRegexp = CreateObject("VBScript.RegExp")
oRegexp.pattern = newPattern
'Set regex options
Dim i As Integer
For i = 1 To Len(flags)
Select Case Mid(flags, i, 1)
Case "i"
oRegexp.ignoreCase = True
Case "g"
oRegexp.Global = True
End Select
Next
'Store regex for optimisation
Set CachedRegex(options & ")" & pattern) = oRegexp
End If
'Get matches object
Dim oMatches As Object
Set oMatches = CachedRegex(options & ")" & pattern).Execute(haystack)
'Get names object
Dim CName As Object
Set CName = CachedNames(options & ")" & pattern)
'Create dictionary to return
Dim oRet As Object
Set oRet = CreateObject("Scripting.Dictionary")
'Fill dictionary with names and indexes
'0 = Whole match
'1,2,3,... = Submatch 1,2,3,...
'"Count" stores the count of matches
'"<<NAME>>" stores the match of a specified name
For i = 1 To CName.Count
oRet(i) = oMatches(0).Submatches(i - 1)
If Not IsEmpty(CName(i - 1).Submatches(0)) Then oRet(CName(i - 1).Submatches(0)) = oMatches(0).Submatches(i - 1)
Next i
oRet(0) = oMatches(0)
oRet("Count") = CName.Count
Set RegexMatch = oRet
End Function
' Procedure for testing 'RegexMatch'.
' - It shows how to convert a date from 'mm/dd/yyyy' to 'dd.mm.yyyy' format.
' - It shows how to retrieve named groups by real name: 'Match.Item("group name")'
' as well as by number: 'Match.Items(group number)'.
' - It shows how to retrieve unnamed groups by number-generated name as well as by number.
' - It shows how to retrieve group count and the whole match by number-generated name as well as by number.
' - It shows that non-capturing groups like '(?:y)?' won't be listed.
' - It shows that left parenthesis inside a character class like '([x(])?' won't disturbe.
' Take notice of:
' - the small difference between 'Item' and 'Items'
' - the quotes in 'Match.Item("number of an unnamed group")'
Sub TestRegexMatch()
Dim Match As Scripting.Dictionary
Set Match = RegexMatch("01/23/2019z", "(?<month>\d\d)\/([x(])?(?<day>\d\d)\/(?:y)?(?<year>\d\d\d\d)(z)?")
Debug.Print Match.Item("day") & "." & Match.Item("month") & "." & Match.Item("year") & " vs. " & Match.Items(2) & "." & Match.Items(0) & "." & Match.Items(3)
Debug.Print "'" & Match.Item("1") & "'" & ", '" & Match.Item("4") & "' vs. '" & Match.Items(1) & "', '" & Match.Items(4) & "'"
Debug.Print Match.Item("98") & " vs. " & Match.Items(Match.Count - 2)
Debug.Print Match.Item("99") & " vs. " & Match.Items(Match.Count - 1)
End Sub
' An implementation of regex which includes named groups and caching implemented in VBA.
' The 'Microsoft VBScript Regular Expressions 5.5' library must be referenced (in VBA-editor: Tools -> References).
' Parameters:
' - haystack: the string the regex is applied on.
' - originalPattern: the regex pattern with or without named groups.
' The group naming has to follow .net regex syntax: '(?<group name>group content)'.
' Group names may contain the following characters: a-z, A-Z, _ (underscore).
' Group names must not be an empty string.
' - options: a string that may contain:
' - 'i' (the regex will work case-insensitive)
' - 'g' (the regex will work globally)
' - 'm' (the regex will work in multi-line mode)
' or any combination of these.
' Returned value: a Scripting.Dictionary object with the following entries:
' - Item 0 or "0", 1 or "1" ... for the groups content/submatches,
' following the convention of VBScript_RegExp_55.SubMatches collection, which is 0-based.
' - Item Match.Count - 2 or "98" for the whole match, assuming that the number of groups is below.
' - Item Match.Count - 1 or "99" for number of groups/submatches.
' Changes compared to the original version:
' - Handles non-capturing and positive and negative lookahead groups.
' - Handles left parenthesis inside a character class.
' - Named groups do not count twice.
' E.g. in the original version the second named group occupies items 3 and 4 of the returned
' dictionary, in this revised version only item 1 (item 0 is the first named group).
' - Additional 'm' option.
' - Fixed fetching cached regexes.
' - Early binding.
' - Some code cleaning.
' For an example take a look at the 'TestRegexMatch' procedure above.
Function RegexMatch(ByVal haystack As String, ByVal originalPattern As String, Optional ByVal options As String) As Scripting.Dictionary
Dim GroupsPattern As String
Dim RealPattern As String
Dim RealRegExp As VBScript_RegExp_55.RegExp
Dim RealMatches As VBScript_RegExp_55.MatchCollection
Dim ReturnData As Scripting.Dictionary
Dim GroupNames As VBScript_RegExp_55.MatchCollection
Dim Ctr As Integer
' Cache regexes and group names for optimisation.
Static CachedRegExps As Scripting.Dictionary
Static CachedGroupNames As Scripting.Dictionary
' Group 'meta'-regex used to detect named and unnamed capturing groups.
Static GroupsRegExp As VBScript_RegExp_55.RegExp
If CachedRegExps Is Nothing Then Set CachedRegExps = New Scripting.Dictionary
If CachedGroupNames Is Nothing Then Set CachedGroupNames = New Scripting.Dictionary
If GroupsRegExp Is Nothing Then
Set GroupsRegExp = New VBScript_RegExp_55.RegExp
' Original version: GroupsRegExp.Pattern = "\((?:\?\<(.*?)\>)?"
GroupsRegExp.Pattern = "\((?!(?:\?:|\?=|\?!|[^\]\[]*?\]))(?:\?<([a-zA-Z0-9_]+?)>)?"
GroupsRegExp.Global = True
End If
' If the pattern isn't cached, create it.
If Not CachedRegExps.Exists("(" & options & ")" & originalPattern) Then
' Prepare the pattern for retrieving named and unnamed groups.
GroupsPattern = Replace(Replace(Replace(Replace(originalPattern, "\\", "X"), "\(", "X"), "\[", "X"), "\]", "X")
' Store group names for optimisation.
CachedGroupNames.Add "(" & options & ")" & originalPattern, GroupsRegExp.Execute(GroupsPattern)
' Create new VBScript regex valid pattern and set regex for this pattern.
RealPattern = GroupsRegExp.Replace(originalPattern, "(")
Set RealRegExp = New VBScript_RegExp_55.RegExp
RealRegExp.Pattern = RealPattern
' Set regex options.
For Ctr = 1 To Len(options)
Select Case Mid(options, Ctr, 1)
Case "i"
RealRegExp.IgnoreCase = True
Case "g"
RealRegExp.Global = True
Case "m"
RealRegExp.MultiLine = True
End Select
Next
' Store this regex for optimisation.
CachedRegExps.Add "(" & options & ")" & originalPattern, RealRegExp
End If
' Get matches.
Set RealMatches = CachedRegExps.Item("(" & options & ")" & originalPattern).Execute(haystack)
' Get group names.
Set GroupNames = CachedGroupNames.Item("(" & options & ")" & originalPattern)
' Create dictionary to return.
Set ReturnData = New Scripting.Dictionary
' Fill dictionary with names and indexes as descibed in the remarks introducing this procedure.
For Ctr = 1 To GroupNames.Count
If IsEmpty(GroupNames(Ctr - 1).SubMatches(0)) Then
ReturnData.Add CStr(Ctr - 1), RealMatches(0).SubMatches(Ctr - 1)
Else
ReturnData.Add GroupNames(Ctr - 1).SubMatches(0), RealMatches(0).SubMatches(Ctr - 1)
End If
Next
ReturnData.Add "98", RealMatches.Item(0)
ReturnData.Add "99", GroupNames.Count
' Return the result.
Set RegexMatch = ReturnData
End Function