2009-12-02 14 views
5

Estoy queriendo crear una expresión regular para el siguiente escenario:Regex - Si contiene '%', sólo puede contener '% 20'

Si una cadena contiene el carácter de porcentaje (%) entonces sólo puede contener lo siguiente: %20, y no puede ir precedido por otro '%'.

Si hubiera, por ejemplo, %25, sería rechazado. Por ejemplo, la siguiente cadena sería válida:

http://www.test.com/?&Name=My%20Name%20Is%20Vader

Pero estos fallaría:

http://www.test.com/?&Name=My%20Name%20Is%20VadersAccountant%25

%%%25

Cualquier ayuda sería muy apreciada,

Kyle


EDIT:

El escenario en pocas palabras es un enlace que se escribe en un estado codificado y luego puso en marcha a través de JavaScript. No funciona la decodificación. Probé decodificación de .net y decodificación de JS, cada uno con el mismo resultado: los resultados permanecen codificados cuando se ejecutan.

+6

¿No sería más fácil hacer esto sin expresiones regulares? ¿Comprobar que el número de apariciones de '%' es exactamente igual al número de apariciones de '% 20'? Por mi parte, encontraría eso mucho más fácil de leer. –

+0

Lamentablemente, no en este escenario. –

+2

Quizás deba describir el escenario. –

Respuesta

5

no requiere un%:

/^[^%]*(%20[^%]*)*$/ 
+0

Gracias Mark, esto se adapta a mis necesidades. –

1

Creo que sería encontrar lo que necesita

/^([^%]|%%|%20)+$/ 

Edición: Añadido caso en el que es %% cadena válida dentro URI
Edit2: Y lo corrigió para el caso donde debería fallar :-)
Edit3:

En caso de que necesite utilizarlo en el editor (lo que explicaría por qué no se puede utilizar de forma más programática), entonces usted tiene que escapar correctamente todos los caracteres especiales, por ejemplo en Vim que la expresión regular debe lool :

/^\([^%]\|%%\|%20\)\+$/ 
+0

Hm, interesante. Esa RE lleva mucho tiempo (no volvió aún) para que coincida con '' http: //www.test.com/? & Name = My% 20Name% 20Is% 20VadersAccountant% 25'' ... ni siquiera sabía infinitos bucles fueron posibles con expresiones regulares. – Joey

+0

Tiene razón, se detuvo antes de la secuencia no válida y coincidió con las cadenas vacías en el ciclo. Corregido ahora – MBO

+0

Parece que funciona ahora. Bonito. – Joey

1

Otra solución si mirada-around no están disponibles:

^([^%]|%([013-9a-fA-F][0-9a-fA-F]|2[1-9a-fA-F]))*$ 
0

Tal vez un mejor enfoque consiste en hacer frente a esa validación después de decodificar esa cadena:

string name = HttpUtility.UrlDecode(Request.QueryString["Name"]); 
+0

Sí, intenté este enfoque antes y desafortunadamente no encajó en el escenario, ¡gracias por la respuesta! –

2

¿Qué idioma estás usando?

La mayoría de los idiomas tienen una función o clase de codificador/decodificador Uri. Sugiero que decodifique primero la cadena y que compruebe si hay caracteres válidos (o inválidos).

i.e.algo como/[\ w]/(vacío es un espacio)

Con una expresión regular en primer lugar, debe respetar que www.example.com/index.html?user=admin & pass = %% 250 means que el pase realmente es "% 250".

+1

Eep, punto muy válido. Gracias. – Joey

+0

Ok, no pude hacer que la expresión regular funcione con esa restricción. Otra cadena de prueba a considerar (que debería fallar de nuevo): "example.com/?pass=%%%25" – Joey

+0

Bugger tienes razón. Necesito actualizar la pregunta con. Desafortunadamente, no tengo la opción de decodificación de URL aquí, por lo que la expresión regular es mi esperanza perdida;) –

0

Acepto el comentario de dominic sobre la pregunta. No use Regex.

Si desea evitar el escaneo de la cadena dos veces, puede buscar iterativamente % y luego verificar que va seguido de 20 y nada más. (Actualización: permitir que un % después de haber sido interpretado como una secuencia literal %nnn)

// pseudo code 
pos = 0 
while (pos = mystring.find(pos, '%')) 
{ 
    if mystring[pos+1] = "%" then 
     pos = pos + 2 // ok, this is a literal, skip ahead 
    else if mystring.substring(pos,2) != "20" 
      return false; // string is invalid 
    end if 
} 
return true; 
+0

¿Por qué se debe rechazar '% 200'? Si quiero escribir un '0' después de un espacio, esto debería ser totalmente posible, en realidad. – Joey

+0

Como dije, no es posible hacer esto en el escenario actual, sin embargo agradezco la respuesta, gracias. –

+0

Sin embargo, su enfoque adolece del mismo problema que el de la expresión regular. Ver la respuesta de SchlaWiener. – Joey

0
/^([^%]|%20)*$/ 
+0

¿A alguien le importaría explicar el voto a la baja? Si mi respuesta es incorrecta, me gustaría saber por qué. – dave4420

+0

Esto significa "O comienza con algo que es"% 20 "o no"% "... – Mez

+0

... y continúa con algo que es o bien'% 20' o no '%', hasta que tocamos el final de la cadena. Que es lo que solicitó el OP. – dave4420

1

Rechazar la cadena si coincide con %[^2][^0]

+0

-1 Esto no permitiría * ninguna cadena que contenga '% 2x' o'% x0' donde 'x' puede ser cualquier carácter arbitrario. – Gumbo

+0

@Gumbo ** Y eso es exactamente lo que OP quiere **. Citando la pregunta "Si una cadena contiene el carácter de porcentaje (%), entonces solo puede contener lo siguiente:% 20, y no puede ir precedida de otro '%'" – Amarghosh

0

Esto requiere una prueba en contra de los patrones "malas". Si permitimos %20, no necesitamos asegurarnos de que exista.

Como otros han dicho antes, %% es válido también ... y %%25 habría %25

El debajo expresión coincide con cualquier cosa que no encaja en las reglas anteriores

/(?<![^%]%)%(?!(20|%))/ 

La primera corchetes comprobar si hay un% antes del carácter (lo que significa que es %%) y también comprueba que no es %%%. luego verifica un% y verifica si el elemento siguiente no concuerda con 20

Esto significa que si algo se identifica con la expresión regular, entonces probablemente debería rechazarla.

+0

No funciona correctamente para ' %% 25' aquí. – Joey

+0

Disculpas ... arreglado. – Mez

Cuestiones relacionadas