我正在寻找创建一个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))
换句话说,我只是试图在一组匹配的括号之间查看.
零宽度前瞻断言是你的朋友。
\n\nFunction 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\nRun Code Online (Sandbox Code Playgroud)\n\n该模式如下:
\n\nterm1在右括号之前term2在右括号之前由于我使用的是前瞻 ( (?=...)),正则表达式引擎实际上从未在字符串上向前移动,因此我可以链接尽可能多的前瞻断言并检查它们。副作用是term1和term2在字符串中出现的顺序并不重要。
我在控制台(“立即窗口”)上测试了它:
\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\nRun Code Online (Sandbox Code Playgroud)\n\n笔记:
\n\nTrue,因为 \xe2\x80\x94 从技术上讲,\xe2\x80\x94aaa和xxx aaa都在同一组括号内。FWIW,这是一个最小的嵌套感知函数,适用于上面的第二个测试用例:
\n\nFunction 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\nRun 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\nRun Code Online (Sandbox Code Playgroud)\n