我正在寻找创建一个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))
换句话说,我只想查看一组匹配的括号。
答案 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
此模式显示为:
term1
发生在闭幕式之前term2
发生在闭幕式之前由于我正在使用前瞻((?=...)
),因此正则表达式引擎实际上从未在字符串上向前移动,所以我可以链接尽可能多的前瞻断言并对它们进行全部检查。副作用是term1
和term2
在字符串中出现的顺序无关紧要。
我在控制台上测试了它(“立即窗口”):
? 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
,因为技术上 - aaa
和xxx aaa
都位于同一组的内容中。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