VBA: 正则表达式(10) -非捕获组(?:Expression)

2024-01-22 15:27:49 浏览数 (2)

文章背景: 最近在看同事写的VBA正则表达式,发现其中用到了非捕获组(?:Expression)。因此,本文对非捕获组的用法做了一些研究。

1 捕获组2 非捕获组3 非捕获组的应用场景

1 捕获组

捕获是指在正则表达式中使用括号来匹配和提取一部分文本。这个被括号包裹的部分被称为捕获组,可以通过VBA代码访问和处理。例如,正则表达式(foo)d 会匹配以foo开头,后面跟着一个或多个数字的字符串。其中(foo)是一个捕获组,表示我们要匹配和提取的是以foo开头的部分。

代码示例:

代码语言:javascript复制
Sub TestRegExp()

    Dim regex As Object
    Set regex = CreateObject("VBScript.RegExp")
    
    Dim inputString As String
    
    inputString = "123-45"
    
    ' 设置正则表达式模式
    regex.Pattern = "(d{3})-(d{2})"
    
    ' 执行匹配
    Dim matches As Object
    Set matches = regex.Execute(inputString)
    
    ' 输出捕获组的内容
    If matches.Count > 0 Then
    
        MsgBox "捕获组 1: " & matches(0).SubMatches(0) & vbCrLf & "捕获组 2: " & matches(0).SubMatches(1)
        
    Else
        MsgBox "没有匹配"
    End If
    
End Sub

对于正则表达式:(d{3})-(d{2}),有两个捕获组,分别是 (d{3})(d{2})。这两个捕获组分别匹配三个数字和两个数字的模式。

代码运行结果:

2 非捕获组

非捕获是指在正则表达式中使用括号来分组,但不会创建一个新的捕获组。非捕获组以问号冒号加圆括号的形式表示,例如(?:foo)d 。这个正则表达式会匹配以foo开头,后面跟着一个或多个数字的字符串,但不会创建一个新的捕获组。在VBA中,我们无法访问或处理非捕获组。

代码示例:

代码语言:javascript复制
Sub TestNonCapturingGroup()

    Dim regex As Object
    Set regex = CreateObject("VBScript.RegExp")
    
    Dim inputString As String
    
    inputString = "a1234b"
    
    ' 设置正则表达式模式
    regex.Pattern = "a(d{2})(?:d{2})b"
    
    ' 执行匹配
    Dim matches As Object
    Set matches = regex.Execute(inputString)
    
    ' 输出捕获组的内容
    If matches.Count > 0 Then
    
        MsgBox "捕获组 1: " & matches(0).SubMatches(0)
        
    Else
        MsgBox "没有匹配"
    End If
    
End Sub

对于正则表达式:a(d{2})(?:d{2})b,(d{2}) 是一个捕获组,匹配两个数字,并且 (?:d{2}) 是一个非捕获组,也匹配两个数字。整个模式匹配的字符串是以 "a" 开头,两个数字,再加两个数字,最后是字母 "b"。

代码运行结果:

3 非捕获组的应用场景

(1) 不需要保留分组内容

当你需要对正则表达式进行分组,但不需要在后续的代码中访问或引用这些分组的内容时,非捕获组是一个好的选择。这有助于保持匹配结果的简洁性,避免生成不必要的捕获组。

(2) 提高性能

在某些情况下,使用非捕获组可以提高正则表达式的性能。捕获组需要额外的处理来存储和维护捕获的内容,而非捕获组则不需要这样的处理。如果性能是一个关键因素,可以考虑使用非捕获组来减少处理开销。

(3) 避免混淆

在某些情况下,正则表达式中可能存在多个嵌套的捕获组,如果你只关心其中的一些组,而不想引入额外的捕获组,可以使用非捕获组来避免混淆。

举例:假设我们想匹配一段文本中的日期,但只关心年份和月份,而不关心具体的日。在这种情况下,可以使用非捕获组来排除日的匹配。

正则表达式:(d{4})-(d{2})(?:-d{2})?

1)在这个例子中,我们使用非捕获组 (?:-d{2})? 来表示日的部分,但并不生成一个独立的捕获组。

2) 这个正则表达式可以匹配类似于 "2022-01" 或 "2022-01-15" 的日期格式,但我们只关心年份和月份。

参考资料:

[1] 正则表达式中 (?:)到底是什么意思(https://segmentfault.com/q/1010000010302799

[2] 正则基础之——非捕获组(https://blog.csdn.net/lxcnn/article/details/4464908

[3] vba捕获 非捕获(https://juejin.cn/s/vba捕获 非捕获

[4] Open AI

0 人点赞