c# - solo - probar expresiones regulares
Uso de RegEx para equilibrar el paréntesis de coincidencia (4)
Las expresiones regulares definitivamente pueden hacer paréntesis equilibrados que coincidan. Puede ser complicado y requiere un par de funciones Regex más avanzadas, pero no es demasiado difícil.
Ejemplo:
var r = new Regex(@"
func([a-zA-Z_][a-zA-Z0-9_]*) # The func name
/( # First ''(''
(?:
[^()] # Match all non-braces
|
(?<open> /( ) # Match ''('', and capture into ''open''
|
(?<-open> /) ) # Match '')'', and delete the ''open'' capture
)+
(?(open)(?!)) # Fails if ''open'' stack isn''t empty!
/) # Last '')''
", RegexOptions.IgnorePatternWhitespace);
Los grupos de coincidencia equilibrada tienen un par de características, pero para este ejemplo, solo estamos usando la función de eliminación de captura. La línea (?<-open> /) )
coincidirá con a )
y eliminará la captura "abierta" anterior.
La línea más difícil es (?(open)(?!))
, así que déjame explicarte. (?(open)
es una expresión condicional que solo coincide si hay una captura "abierta". (?!)
es una expresión negativa que siempre falla. Por lo tanto, (?(open)(?!))
dice "si hay una captura abierta, luego falla ".
La documentación de Microsoft también fue muy útil.
Estoy tratando de crear una expresión RegEx de .NET que equilibrará adecuadamente mi paréntesis. Tengo la siguiente expresión RegEx:
func([a-zA-Z_][a-zA-Z0-9_]*)/(.*/)
La cadena con la que trato de coincidir es esta:
"test -> funcPow((3),2) * (9+1)"
Lo que debería suceder es que Regex debe hacer coincidir todo, desde funcPow
hasta el segundo paréntesis de cierre. Debería detenerse después del segundo paréntesis de cierre. En cambio, está haciendo coincidir todo el camino hasta el último paréntesis de cierre. RegEx está devolviendo esto:
"funcPow((3),2) * (9+1)"
Debería devolver esto:
"funcPow((3),2)"
Cualquier ayuda en esto sería apreciada.
Las expresiones regulares solo funcionan en idiomas regulares . Esto significa que una expresión regular puede encontrar cosas del tipo "cualquier combinación de a''s y b''s". ( babbabaaa
o babbabaaa
etc.) Pero no pueden encontrar " n a''s, one b, n a''s". (A a^nba^n
) Las expresiones regulares no pueden garantizar que el primer conjunto de a coincida con el segundo conjunto de a.
Debido a esto, no pueden hacer coincidir el mismo número de paréntesis de apertura y cierre. Sería bastante fácil escribir una función que atraviese la cadena un carácter a la vez. Tener dos contadores, uno para abrir paren, uno para cerrar. incremente los punteros a medida que recorre la cadena, si opening_paren_count != closing_parent_count
devuelve false.
Usando grupos balanceados, es:
Regex rx = new Regex(@"func([a-zA-Z_][a-zA-Z0-9_]*)/(((?<BR>/()|(?<-BR>/))|[^()]*)+/)");
var match = rx.Match("funcPow((3),2) * (9+1)");
var str = match.Value; // funcPow((3),2)
(?<BR>/()|(?<-BR>/))
son un grupo de equilibrio (el BR
que utilicé para el nombre es para Brackets
). Es más claro de esta manera (?<BR>
/ ( )|(?<-BR>
/) )
tal vez, por lo que el /(
y /)
son más "evidentes".
Si realmente te odias a ti mismo (y al mundo / tus compañeros programadores) lo suficiente como para usar estas cosas, te sugiero usar RegexOptions.IgnorePatternWhitespace
y "rociar" espacios en blanco en todas partes :-)
func[a-zA-Z0-9_]*/((([^()])|(/([^()]*/)))*/)
Puede usar eso, pero si está trabajando con .NET, puede haber mejores alternativas.
Esta parte ya lo sabes:
func[a-zA-Z0-9_]*/( --weird part-- /)
La parte de la segunda parte solo significa; (
permita que cualquier caracter, o |
cualquier seccion (.*)
exista tantas veces como quiera )*
. El único problema es que no puedes unir ningún personaje .
, debe usar [^()]
para excluir el paréntesis.
(([^()])|(/([^()]*/)))*