Null-Breite Vorgriff asserttions Ihr Freund ist.
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
Dieses Muster lautet:
- von einer Öffnung paren starten, überprüfen:
- die einen passenden Schließ paren irgendwo und keine verschachtelten Pars innerhalb
- folgt, dass
term1
vor dem auftritt Schließen paren
- , dass
term2
vor dem Schließen auftritt
Da ich Vorgriffs ((?=...)
) verwendet wird, bewegt sich nie die Regex-Engine tatsächlich vorwärts auf der Schnur, so kann ich Kette so viele Vorgriffs Behauptungen und haben sie alle überprüft.Ein Nebeneffekt ist, dass die Reihenfolge, in der term1
und term2
in der Zeichenfolge auftreten, keine Rolle spielt.
I testete ihn auf der Konsole ("Immediate Window"):
? 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
Anmerkungen:
- Der zweite Test-Ausbeuten
True
da-technisch sowohl aaa
und xxx aaa
innerhalb desselben Satzes sind von Parens.
- Regex kann nicht mit verschachtelten Strukturen umgehen. Mit regulären Ausdrücken erhalten Sie nie geschachtelte Klammern. Sie werden nie "ein passender Satz von Parens" mit Regex allein finden - nur ein öffnendes/schließendes Paar, das keine anderen Paren dazwischen hat. Schreiben Sie einen Parser, wenn Sie mit der Verschachtelung umgehen müssen.
- Machen Sie einen Verweis auf "Microsoft VBScript Regular Expressions 5.5" in Ihrem Projekt.
FWIW, hier ist eine minimale Verschachtelung-aware-Funktion, die oben für den zweiten Testfall funktioniert:
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
Console:
? 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
Können Sie die Klammern entfernen und rufen [ 'Split'] (http://msdn.microsoft.com/en-us/library/6x627e5f (v = vs.80) .aspx) um die Einträge in ein Array zu trennen, das Sie durchsuchen können? – mellamokb
können Sie nicht einfach die InStr-Funktion dafür verwenden? Sie könnten einfach eine boolesche Variable oder etwas verwenden und sie auf "true" setzen, wenn sie einen Ort für die gesuchte Phrase in der Zeichenfolge findet? InStr Funktion hier gefunden: http://msdn.microsoft.com/en-us/library/8460tsh1(v=vs.80).aspx –
Ich habe versucht, Ihre Frage bestmöglich zu beantworten, aber Sie sind unklar in Ihrem Problem Definition. ** a) ** Regex wird niemals eine Vorstellung von * "passenden Klammern" * haben. Es ist technisch unmöglich. ** b) ** Sie scheinen davon auszugehen, dass "," eine Art Trennzeichen ist, aber Sie definieren das nie wirklich. – Tomalak