de ancho cero son de su amigo.
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
Este patrón se lee como:
- a partir de una paren de apertura, visita:
- que un paren de cierre coincidente sigue en algún lugar y no hay parens anidado dentro
- que
term1
se produce antes de la Paréntesis de cierre
- que
term2
ocurre antes de los paréntesis de cierre
Desde que estoy usando preanálisis ((?=...)
), el motor de expresiones regulares en realidad nunca se mueve hacia adelante en la cadena, por lo que puede encadenar tantas afirmaciones de preanálisis y hacer que todos se comprueban.Un efecto secundario es que el orden en el que term1
y term2
aparecen en la cadena no es relevante.
he comprobado en la consola ("ventana Inmediato"):
? 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
Notas:
- rendimientos La segunda prueba
True
porque-técnicamente tanto aaa
y xxx aaa
están dentro del mismo conjunto de parens.
- Regex no puede tratar con estructuras anidadas. Nunca se obtendrán paréntesis anidados a la derecha con expresiones regulares. Nunca podrá encontrar "un conjunto coincidente de parens" con expresiones regulares solamente, solo un par de apertura/cierre que no tiene otros pares intermedios. Escribe un analizador si necesitas manejar el anidamiento.
- Haga una referencia a "Microsoft VBScript Regular Expressions 5.5" en su proyecto.
Fwiw, he aquí una función de anidación-conscientes mínima que trabaja para el segundo caso de prueba anterior:
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
Consola:
? 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
Se puede eliminar los paréntesis y llame a [ 'Split'] (http://msdn.microsoft.com/en-us/library/6x627e5f (v = vs.80) .aspx) para separar las entradas en una matriz que puede buscar? – mellamokb
¿no podría usar la función InStr para esto? ¿Podría simplemente usar una variable booleana o algo así y establecerlo en verdadero si encuentra una ubicación para la frase que está buscando en la cadena? Función InStr encontrada aquí: http://msdn.microsoft.com/en-us/library/8460tsh1(v=vs.80).aspx –
Intenté responder a su pregunta lo mejor posible, pero no está claro en su definición del problema. ** a) ** Regex nunca tendrá la noción de * "paréntesis coincidentes" *. Es técnicamente imposible. ** b) ** Pareces asumir que ',' es algún tipo de separador, pero nunca realmente defines eso. – Tomalak