validar solo regulares regular probar minimo letras expresiones expresion espacios espacio ejemplos caracteres cantidad blanco alfanumerico c++ python regex parsing recursion

c++ - solo - validar expresiones regulares c#



Expresión regular para detectar C++ terminado en dos puntos para ciclos de while (9)

Como Frank sugirió, esto es lo mejor sin expresiones regulares. Aquí hay (un feo) delineador:

match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]

Coincidencia con la línea troll se menciona en su comentario:

orig_string = "for (int i = 0; i < 10; doSomethingTo(/"(/"));" match_string = orig_string[orig_string.index("("):len(orig_string)-orig_string[::-1].index(")")]

devuelve (int i = 0; i < 10; doSomethingTo("("))

Esto funciona pasando la cadena hacia adelante hasta que alcanza la primera paren abierta, y luego hacia atrás hasta que alcanza la primera paren de cierre. Luego usa estos dos índices para cortar la cadena.

En mi aplicación de Python, necesito escribir una expresión regular que coincida con un C ++ for o while loop que ha terminado con un punto y coma ( ; ). Por ejemplo, debe coincidir con esto:

for (int i = 0; i < 10; i++);

... pero no esto:

for (int i = 0; i < 10; i++)

Esto parece trivial a primera vista, hasta que se da cuenta de que el texto entre el paréntesis de apertura y cierre puede contener otros paréntesis, por ejemplo:

for (int i = funcA(); i < funcB(); i++);

Estoy usando el módulo python.re En este momento mi expresión regular se ve así (he dejado mis comentarios para que pueda entenderlo más fácilmente):

# match any line that begins with a "for" or "while" statement: ^/s*(for|while)/s* /( # match the initial opening parenthesis # Now make a named group ''balanced'' which matches a balanced substring. (?P<balanced> # A balanced substring is either something that is not a parenthesis: [^()] | # …or a parenthesised string: /( # A parenthesised string begins with an opening parenthesis (?P=balanced)* # …followed by a sequence of balanced substrings /) # …and ends with a closing parenthesis )* # Look for a sequence of balanced substrings /) # Finally, the outer closing parenthesis. # must end with a semi-colon to match: /s*;/s*

Esto funciona perfectamente para todos los casos anteriores, pero se rompe tan pronto como lo intentas y hace que la tercera parte del bucle for contenga una función, como esta:

for (int i = 0; i < 10; doSomethingTo(i));

Creo que se rompe porque tan pronto como pones un texto entre el paréntesis de apertura y cierre, el grupo "equilibrado" coincide con el texto contenido, y por lo tanto la parte (?P=balanced) ya no funciona, ya que no lo hará coincidencia (debido al hecho de que el texto dentro del paréntesis es diferente).

En mi código de Python estoy usando las banderas VERBOSE y MULTILINE, y creo la expresión regular de esta manera:

REGEX_STR = r"""# match any line that begins with a "for" or "while" statement: ^/s*(for|while)/s* /( # match the initial opening parenthesis # Now make a named group ''balanced'' which matches # a balanced substring. (?P<balanced> # A balanced substring is either something that is not a parenthesis: [^()] | # …or a parenthesised string: /( # A parenthesised string begins with an opening parenthesis (?P=balanced)* # …followed by a sequence of balanced substrings /) # …and ends with a closing parenthesis )* # Look for a sequence of balanced substrings /) # Finally, the outer closing parenthesis. # must end with a semi-colon to match: /s*;/s*""" REGEX_OBJ = re.compile(REGEX_STR, re.MULTILINE| re.VERBOSE)

¿Alguien puede sugerir una mejora a esta expresión regular? Se me está volviendo demasiado complicado entenderlo.


Este es el tipo de cosas que realmente no debería hacer con una expresión regular. Solo analice la cadena un carácter a la vez, manteniendo un registro de los paréntesis de apertura / cierre.

Si esto es todo lo que está buscando, definitivamente no necesita un grabador / analizador de gramática C ++ en toda regla. Si quieres practicar, puedes escribir un pequeño analizador decente recursivo, pero incluso eso es demasiado para emparejar paréntesis.


Este es un gran ejemplo de usar la herramienta incorrecta para el trabajo. Las expresiones regulares no manejan muy bien las subclases anidadas arbitrariamente. Lo que debe hacer en su lugar es usar un analizador y analizador real (una gramática para C ++ debería ser fácil de encontrar) y buscar cuerpos de bucle inesperadamente vacíos.


Greg es absolutamente correcto. Este tipo de análisis no puede hacerse con expresiones regulares. Supongo que es posible construir una monstruosidad horrenda que funcione en muchos casos, pero luego te encontrarás con algo que sí lo haga.

Realmente necesitas usar técnicas de análisis más tradicionales. Por ejemplo, es bastante sencillo escribir un analizador decente recursivo para hacer lo que necesita.


Ni siquiera le prestaría atención al contenido de los parens.

Simplemente haga coincidir cualquier línea que comience con y termine con punto y coma:

^/t*for.+;$

A menos que tenga declaraciones divididas en varias líneas, ¿funcionará bien?


No sé que Regex manejaría algo así muy bien. Pruebe algo como esto

line = line.Trim(); if(line.StartsWith("for") && line.EndsWith(";")){ //your code here }


Otro pensamiento que ignora paréntesis y trata el for como una construcción que contiene tres valores delimitados por punto y coma:

for/s*/([^;]+;[^;]+;[^;]+/)/s*;

Esta opción funciona incluso cuando se divide en varias líneas (una vez MULTILINE habilitado), pero se supone que for ( ... ; ... ; ... ) es la única construcción válida, por lo que no funcionaría con a for ( x in y ) construir u otras desviaciones.

También asume que no hay funciones que contengan punto y coma como argumentos, como por ejemplo:

for ( var i = 0; i < ListLen(''a;b;c'','';'') ; i++ );

Si este es un caso probable depende de lo que realmente está haciendo esto.


Podrías escribir una rutina pequeña y muy simple que lo haga, sin usar una expresión regular:

  • Establezca un contador de posición pos para que apunte justo antes del paréntesis de apertura después de su for o while .
  • Establezca un contador de corchetes abiertos openBr en 0 .
  • Ahora siga incrementando pos , leyendo los caracteres en las posiciones respectivas, e incremente openBr cuando vea un corchete de apertura, y disminuya cuando vea un corchete de cierre. Esto lo incrementará una vez al principio, para el primer paréntesis de apertura en " for ( ", incremente y disminuya un poco más para algunos paréntesis intermedios, y vuelva a establecerlo en 0 cuando se cierra el paréntesis.
  • Entonces, deténgase cuando openBr sea 0 nuevamente.

La posición de parada es su corchete de cierre de for(...) . Ahora puede verificar si hay un punto y coma a continuación o no.


Prueba esta expresión regular

^/s*(for|while)/s* /( (?P<balanced> [^()]* | (?P=balanced) /) /s*;/s

Quité el envoltorio /( /) alrededor (?P=balanced) y moví * a detrás de la secuencia any not paren. He tenido este trabajo con boost xpressive, y volví a revisar ese sitio web ( Xpressive ) para actualizar mi memoria.