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

Jac*_*ble 5 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))

换句话说,我只是试图在一组匹配的括号之间查看.

Tom*_*lak 1

零宽度前瞻断言是你的朋友。

\n\n
Function FindInParen(str As String, term1 As String, term2 As String) As Boolean\n  Dim re As New VBScript_RegExp_55.RegExp\n\n  re.Pattern = "\\(" & _\n               "(?=[^()]*)\\)" & _\n               "(?=[^()]*\\b" & RegexEscape(term1) & "\\b)" & _\n               "(?=[^()]*\\b" & RegexEscape(term2) & "\\b)"\n\n  FindInParen = re.Test(str)\nEnd Function\n\nFunction RegexEscape(str As String) As String\n  With New VBScript_RegExp_55.RegExp\n    .Pattern = "[.+*?^$|\\[\\](){}\\\\]"\n    .Global = True\n    RegexEscape = .Replace(str, "\\$&")\n  End With\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n\n

该模式如下:

\n\n
    \n
  • 从左括号开始,检查:\n
      \n
    • 匹配的右括号跟随在某处并且内部没有嵌套括号
    • \n
    • 发生term1在右括号之前
    • \n
    • 发生term2在右括号之前
    • \n
  • \n
\n\n

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

\n\n

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

\n\n
? FindInParen("(aaa, bbb, ccc, ddd, xxx aaa)", "aaa", "xxx aaa")\nTrue\n\n? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "aaa", "xxx aaa")\nTrue\n\n? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "bbb", "xxx aaa")\nFalse\n
Run Code Online (Sandbox Code Playgroud)\n\n

笔记:

\n\n
    \n
  • 第二个测试会产生结果True,因为 \xe2\x80\x94 从技术上讲,\xe2\x80\x94aaaxxx aaa都在同一组括号内。
  • \n
  • 正则表达式无法处理嵌套结构。你永远不会用正则表达式得到正确的嵌套括号。仅使用正则表达式,您将永远无法找到“一组匹配的括号” - 只能找到中间没有其他括号的开始/结束对。如果需要处理嵌套,请编写一个解析器。
  • \n
  • 在您的项目中引用“Microsoft VBScript Regular Expressions 5.5”
  • \n
\n\n
\n\n

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

\n\n
Function FindInParen(str As String, term1 As String, term2 As String) As Boolean\n  Dim parenPair As New VBScript_RegExp_55.RegExp\n  Dim terms As New VBScript_RegExp_55.RegExp\n  Dim matches As VBScript_RegExp_55.MatchCollection\n\n  FindInParen = False\n  parenPair.Pattern = "\\([^()]*\\)"\n  terms.Pattern = "(?=.*?[(,]\\s*(?=\\b" & RegexEscape(Trim(term1)) & "\\b))" & _\n                  "(?=.*?[(,]\\s*(?=\\b" & RegexEscape(Trim(term2)) & "\\b))"\n\n  Do\n    Set matches = parenPair.Execute(str)\n    If matches.Count Then\n      If terms.Test(matches(0).Value) Then\n        Debug.Print "found here: " & matches(0).Value\n        FindInParen = True\n      End If\n      str = parenPair.Replace(str, "[...]")\n    End If\n  Loop Until FindInParen Or matches.Count = 0\n\n  If Not FindInParen Then\n    Debug.Print "not found"\n  End If\n\n  If InStr("(", str) > 0 Or InStr(")", str) > 0 Then\n    Debug.Print "mis-matched parens"\n  End If\nEnd Function\n
Run Code Online (Sandbox Code Playgroud)\n\n

安慰:

\n\n
? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "aaa", "xxx aaa")\nnot found\nFalse\n\n? FindInParen("(aaa, bbb, ccc, ddd, (eee, xxx aaa))", "eee", "xxx aaa")\nfound here: (eee, xxx aaa)\nTrue\n
Run Code Online (Sandbox Code Playgroud)\n