VBA正则表达式 - 匹配不以特定单词开头的表达式

时间:2012-07-30 15:06:55

标签: regex vba

我正在寻找创建一个VBA正则表达式,它将在一组括号中找到两个特定字符串的存在。

例如,在此表达式中:

(aaa,bbb,ccc,ddd,xxx aaa)

它应该以某种方式告诉我它在表达式中找到了“aaa”和“xxx aaa”。即,由于前面没有“xxxx”的“aaa”匹配,并且表达式中的“xxx aaa”也匹配,它应该返回true。由于这两个序列可以以任何顺序出现,反之亦然。

所以我认为表达式是这样的:

“( xxx aaa” [^ x] [^ x] [^ x] [^ x] aaa )“

在一个订单中找到单词并

“( aaa” [^ x] [^ x] [^ x] [^ x] xxx aaa )“

以另一个顺序的单词。

这有意义吗?还是有更好的方法?

我知道这正在改变规范,但有一个重要的附录 - 术语之间不能有任何中间括号。

例如,这不应该匹配:

(aaa,bbb,ccc,ddd,(eee,xxx aaa))

换句话说,我只想查看一组匹配的括号。

2 个答案:

答案 0 :(得分:1)

从你的问题中确切地说你的想法并不是很清楚(也许这里并不真正需要Regexp),但这可能很接近:

Sub Tester()
    RegexpTest ("(aaa, bbb, ccc, ddd, xxx aaa)")
End Sub


Sub RegexpTest(txt As String)
    Dim re As Object
    Dim allMatches, m

    Set re = CreateObject("VBScript.RegExp")
    re.Pattern = "([^,\(]*aaa)"
    re.ignorecase = True
    re.Global = True

    Set allMatches = re.Execute(txt)

    For Each m In allMatches
        Debug.Print Trim(m)
    Next m

End Sub

答案 1 :(得分:1)

零宽度前瞻声明是你的朋友。

Function FindInParen(str As String, term1 As String, term2 As String) As Boolean
  Dim re As New VBScript_RegExp_55.RegExp

  re.Pattern = "\(" & _
               "(?=[^()]*)\)" & _
               "(?=[^()]*\b" & RegexEscape(term1) & "\b)" & _
               "(?=[^()]*\b" & RegexEscape(term2) & "\b)"

  FindInParen = re.Test(str)
End Function

Function RegexEscape(str As String) As String
  With New VBScript_RegExp_55.RegExp
    .Pattern = "[.+*?^$|\[\](){}\\]"
    .Global = True
    RegexEscape = .Replace(str, "\$&")
  End With
End Function

此模式显示为:

  • 从开幕式开始,检查:
    • 匹配的关闭paren跟在某处,而
    • 中没有嵌套的parens
    • term1发生在闭幕式之前
    • term2发生在闭幕式之前

由于我正在使用前瞻((?=...)),因此正则表达式引擎实际上从未在字符串上向前移动,所以我可以链接尽可能多的前瞻断言并对它们进行全部检查。副作用是term1term2在字符串中出现的顺序无关紧要。

我在控制台上测试了它(“立即窗口”):

? FindInParen("(aaa, bbb, ccc, ddd, xxx aaa)", "aaa", "xxx aaa")
True

? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "aaa", "xxx aaa")
True

? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "bbb", "xxx aaa")
False

注意:

  • 第二次测试产生True,因为技术上 - aaaxxx aaa都位于同一组的内容中。
  • 正则表达式无法处理嵌套结构。您永远不会使用正则表达式获得嵌套括号。你永远无法单独使用正则表达式来找到“匹配的一组parens” - 只有一个中间没有其他parens的开/关对。如果需要处理嵌套,请编写解析器。
  • 在项目中引用“Microsoft VBScript Regular Expressions 5.5”

FWIW,这是一个最小的嵌套感知功能,适用于上面的第二个测试用例:

Function FindInParen(str As String, term1 As String, term2 As String) As Boolean
  Dim parenPair As New VBScript_RegExp_55.RegExp
  Dim terms As New VBScript_RegExp_55.RegExp
  Dim matches As VBScript_RegExp_55.MatchCollection

  FindInParen = False
  parenPair.Pattern = "\([^()]*\)"
  terms.Pattern = "(?=.*?[(,]\s*(?=\b" & RegexEscape(Trim(term1)) & "\b))" & _
                  "(?=.*?[(,]\s*(?=\b" & RegexEscape(Trim(term2)) & "\b))"

  Do
    Set matches = parenPair.Execute(str)
    If matches.Count Then
      If terms.Test(matches(0).Value) Then
        Debug.Print "found here: " & matches(0).Value
        FindInParen = True
      End If
      str = parenPair.Replace(str, "[...]")
    End If
  Loop Until FindInParen Or matches.Count = 0

  If Not FindInParen Then
    Debug.Print "not found"
  End If

  If InStr("(", str) > 0 Or InStr(")", str) > 0 Then
    Debug.Print "mis-matched parens"
  End If
End Function

控制台:

? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "aaa", "xxx aaa")
not found
False

? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "eee", "xxx aaa")
found here: (eee, xxx aaa)
True