regex - regulares - ¿Hay una expresión regular para detectar una expresión regular válida?
expresiones regulares jquery (8)
Aunque es perfectamente posible usar una expresión regular recursiva como MizardX ha publicado, para este tipo de cosas es mucho más útil un analizador. Las expresiones regulares estaban pensadas para ser utilizadas con lenguajes regulares, ser recursivo o tener grupos de balanceo es solo un parche.
El lenguaje que define las expresiones regulares válidas es en realidad una gramática libre de contexto, y debe usar un analizador adecuado para su manejo. Aquí hay un ejemplo de un proyecto universitario para analizar expresiones regulares simples (sin la mayoría de las construcciones). Utiliza JavaCC. Y sí, los comentarios están en español, aunque los nombres de los métodos son bastante autoexplicativos.
SKIP :
{
" "
| "/r"
| "/t"
| "/n"
}
TOKEN :
{
< DIGITO: ["0" - "9"] >
| < MAYUSCULA: ["A" - "Z"] >
| < MINUSCULA: ["a" - "z"] >
| < LAMBDA: "LAMBDA" >
| < VACIO: "VACIO" >
}
IRegularExpression Expression() :
{
IRegularExpression r;
}
{
r=Alternation() { return r; }
}
// Matchea disyunciones: ER | ER
IRegularExpression Alternation() :
{
IRegularExpression r1 = null, r2 = null;
}
{
r1=Concatenation() ( "|" r2=Alternation() )?
{
if (r2 == null) {
return r1;
} else {
return createAlternation(r1,r2);
}
}
}
// Matchea concatenaciones: ER.ER
IRegularExpression Concatenation() :
{
IRegularExpression r1 = null, r2 = null;
}
{
r1=Repetition() ( "." r2=Repetition() { r1 = createConcatenation(r1,r2); } )*
{ return r1; }
}
// Matchea repeticiones: ER*
IRegularExpression Repetition() :
{
IRegularExpression r;
}
{
r=Atom() ( "*" { r = createRepetition(r); } )*
{ return r; }
}
// Matchea regex atomicas: (ER), Terminal, Vacio, Lambda
IRegularExpression Atom() :
{
String t;
IRegularExpression r;
}
{
( "(" r=Expression() ")" {return r;})
| t=Terminal() { return createTerminal(t); }
| <LAMBDA> { return createLambda(); }
| <VACIO> { return createEmpty(); }
}
// Matchea un terminal (digito o minuscula) y devuelve su valor
String Terminal() :
{
Token t;
}
{
( t=<DIGITO> | t=<MINUSCULA> ) { return t.image; }
}
¿Es posible detectar una expresión regular válida con otra expresión regular? Si es así, por favor dé el código de ejemplo a continuación.
Buena pregunta. Los verdaderos lenguajes regulares no pueden decidir entre paréntesis bien formados arbitrariamente profundamente anidados. Es decir, si su alfabeto contiene ''('' y '')'', el objetivo es decidir si una cadena de estos tiene paréntesis coincidentes bien formados. Dado que este es un requisito necesario para las expresiones regulares, la respuesta es no.
Sin embargo: si afloja el requisito y agrega recursión, probablemente pueda hacerlo. La razón es que la recursión puede actuar como una "pila", lo que le permite "contar" la profundidad de anidamiento actual presionando sobre esta pila.
Russ Cox ha escrito un maravilloso tratado sobre la implementación del motor de expresiones regulares : la coincidencia de expresiones regulares puede ser simple y rápida
Este example en la wiki de pyparsing proporciona una gramática para analizar algunas expresiones regulares, con el propósito de devolver el conjunto de cadenas coincidentes. Como tal, rechaza aquellos puntos que incluyen términos de repetición ilimitados, como ''+'' y ''*''. Pero debería darle una idea acerca de cómo estructurar un analizador que procesaría los re.
Improbable.
try..catch
en un try..catch
o lo que ofrezca su idioma.
No, si está hablando estrictamente sobre expresiones regulares y no incluye algunas implementaciones de expresiones regulares que en realidad son gramáticas libres de contexto.
Hay una limitación de las expresiones regulares que hace que sea imposible escribir una expresión regular que coincida con todas y solo expresiones regulares. No puede hacer coincidir implementaciones como llaves que están emparejadas. Las expresiones regulares utilizan muchas de estas construcciones, tomemos [] como ejemplo. Siempre que haya un [debe haber una coincidencia]. Bastante simple para un regex "[. *]".
Lo que hace imposible para las expresiones regulares es que se pueden anidar. ¿Cómo se puede escribir una expresión regular que coincida con corchetes anidados? La respuesta es que no puedes sin un regex infinitamente largo. Puede hacer coincidir cualquier número de parentes anidados mediante la fuerza bruta, pero nunca puede igualar un conjunto arbitrariamente largo de paréntesis anidados.
Esta capacidad a menudo se denomina conteo (se cuenta la profundidad del anidamiento). Una expresión regular por definición no tiene la capacidad de contar.
EDITAR: Terminé escribiendo una entrada de blog sobre esto: Limitaciones de expresiones regulares
Prueba este ...
//regular expression for email
var pattern = /^(([^<>()[/]//.,;:/s@/"]+(/.[^<>()[/]//.,;:/s@/"]+)*)|(/".+/"))@((/[[0-9]{1,3}/.[0-9]{1,3}/.[0-9]{1,3}/.[0-9]{1,3}/])|(([a-zA-Z/-0-9]+/.)+[a-zA-Z]{2,}))$/;
if(pattern.test(email)){
return true;
} else {
return false;
}
Puede enviar la expresión regular a preg_match que devolverá false si la expresión regular no es válida. No olvide usar la ''@'' para suprimir los mensajes de error:
@preg_match($regexToTest, '''');
- devolverá 1 si la expresión regular es ''//''.
- devolverá 0 si la expresión regular está bien.
- volverá falso de lo contrario.
/
^ # start of string
( # first group start
(?:
(?:[^?+*{}()[/]//|]+ # literals and ^, $
| //. # escaped characters
| /[ (?: /^?//. | /^[^//] | [^//^] ) # character classes
(?: [^/]//]+ | //. )* /]
| /( (?:/?[:=!]|/?<[=!]|/?>)? (?1)?? /) # parenthesis, with recursive content
| /(/? (?:R|[+-]?/d+) /) # recursive matching
)
(?: (?:[?+*]|/{/d+(?:,/d*)?/}) [?+]? )? # quantifiers
| /| # alternative
)* # repeat content
) # end first group
$ # end of string
/
Esta es una expresión regular recursiva, y no es compatible con muchos motores de expresiones regulares. Los basados en PCRE deberían apoyarlo.
Sin espacios en blanco y comentarios:
/^((?:(?:[^?+*{}()[/]//|]+|//.|/[(?:/^?//.|/^[^//]|[^//^])(?:[^/]//]+|//.)*/]|/((?:/?[:=!]|/?<[=!]|/?>)?(?1)??/)|/(/?(?:R|[+-]?/d+)/))(?:(?:[?+*]|/{/d+(?:,/d*)?/})[?+]?)?|/|)*)$/
.NET no soporta recursion directamente. (Las construcciones (?1)
y (?R)
.) La recursión se tendría que convertir para contar grupos equilibrados:
^ # start of string
(?:
(?: [^?+*{}()[/]//|]+ # literals and ^, $
| //. # escaped characters
| /[ (?: /^?//. | /^[^//] | [^//^] ) # character classes
(?: [^/]//]+ | //. )* /]
| /( (?:/?[:=!]
| /?<[=!]
| /?>
| /?<[^/W/d]/w*>
| /?''[^/W/d]/w*''
)? # opening of group
(?<N>) # increment counter
| /) # closing of group
(?<-N>) # decrement counter
)
(?: (?:[?+*]|/{/d+(?:,/d*)?/}) [?+]? )? # quantifiers
| /| # alternative
)* # repeat content
$ # end of string
(?(N)(?!)) # fail if counter is non-zero.
Comprimido:
^(?:(?:[^?+*{}()[/]//|]+|//.|/[(?:/^?//.|/^[^//]|[^//^])(?:[^/]//]+|//.)*/]|/((?:/?[:=!]|/?<[=!]|/?>|/?<[^/W/d]/w*>|/?''[^/W/d]/w*'')?(?<N>)|/)(?<-N>))(?:(?:[?+*]|/{/d+(?:,/d*)?/})[?+]?)?|/|)*$(?(N)(?!))