2011-08-19 26 views
8

me encontré con esta expresión regular en el código fuente de jQuery:¿Qué agrega esta parte de expresión regular?

... 
rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, 
... 

me preguntaba por qué era bastante complicado. Estoy especialmente interesado en la razón detrás de la segunda parte:

(?:.*? rv:([\w.]+))? 

hice algunas investigaciones, pero no pude averiguar lo que esta parte de la expresión regular agrega.

(?:)  to match but not capture 
.*?  any amount of any character 
rv:  something literal 
([\w.]+) one or more word characters or a dot 
?   appear 0 or 1 time 

Particularmente, la última ? no tiene mucho sentido para mí. La segunda parte completa coincide si existe o no una subcadena tal como se define en esa segunda parte. Con un poco de ensayo y error no parece la expresión regular a diferir de simplemente:

/(mozilla)/ 

Podría alguien arrojar alguna luz sobre lo que se supone que la segunda parte de la expresión regular para hacer? ¿Qué lo restringe? ¿Qué cadena falla que pasa /(mozilla)/ o al revés?

+0

Sospecho que es trabajar en torno a algunos navegadores Mozilla falsificar poniéndolo en su cadena de agente de usuario. –

+0

¿Puedes proporcionar un poco más de contexto? ¿Esto era parte de un plugin jQuery? ¿Si es así, Cuál? Saber dónde aparece este código podría arrojar algo de luz sobre/por qué/el autor quería este patrón en particular y, por lo tanto, qué está haciendo el patrón. – jefflunt

+0

@Rafe Kettler: No estoy seguro de que te haya entendido correctamente. ¿Qué agrega la expresión regular para evitar falsificadores? – pimvdb

Respuesta

4

Las dos expresiones regulares coincidirían con las mismas cadenas, pero almacenarían información diferente en sus grupos de captura.

para la cadena: mozilla asdf rv:sadf

/(mozilla)(?:.*? rv:([\w.]+))?/ 
$0 = 'mozilla asdf rv:sadf' 
$1 = 'mozilla' 
$2 = 'sadf' 

/(mozilla)/ 
$0 = 'mozilla' 
$1 = 'mozilla' 
$2 = '' 
1

El ([\w.]+) dentro de (?:.*? rv:([\w.]+)) está capturando, por lo que quizás esta expresión regular se usó para obtener el número de revisión en el pasado (sin embargo, parece que actualmente jquery solo verifica si la expresión regular coincide).

2

En primer lugar, me gustaría aclarar la diferencia entre:

.*? - non-greedy match 
.* - greedy match 

El no expansivo coincidirá con el menor número de bytes posibles (teniendo en cuenta el resto de la cadena de búsqueda), y el goloso coinciden más

dado una cadena:

mozilla some text here rv:abc xyz 

La expresión regular volverá tanto 'Mozilla' y 'ABC'. Pero si el 'rv:' no existe, la expresión regular aún devolverá 'mozilla'.

+0

Cierto, pero generalmente se los conoce como "no codiciosos" y "codiciosos", respectivamente. –

+0

Sí. Mi memoria es un poco divertida de esa manera. Voy a editar –

0

(pat) es un delimitador de patrón para la búsqueda de un patrón contenida completo. (?: Pat) es la negación de arriba, al igual que el paréntesis del conjunto de caracteres [^] es la negación de []. ¡En javascript, la negación ocurre con ! . coincide con cualquier carácter, * es un cuantificador de coincidencias, y en motores Regex más nuevos también puede escribirse como {0,} (¡pero esos tres caracteres adicionales pueden provocar una muerte prematura de tu teclado!) ? cuantificador de correspondencia redundante: puede coincidir con cero o una vez rv: ([. \ w] +) .... rv literal

otra subcoincidencia, puede coincidir con cero o una vez dentro del partido matriz )? [\ w.] ...juego de caracteres, con w "\ w" escapado: cualquier carácter alfanumérico, también conocido como [a-zA-Z0-9_] seguido de un punto literal, y por cuantificador de partido +, puede ocurrir una o más veces

Para ingeniero de reversa el significado de la coincidencia de patrón: simplemente evalúa de izquierda a derecha, en un editor de texto y sustituye las letras por literales aleatorios que te vienen a la mente y para los que coincide cada sub-expresión. Luego tome un paso atrás y reflexione sobre para qué podría haber sido la expresión regular.

+1

Aproveche la función SO [formato de código] (http://stackoverflow.com/editing-help#code); como está ahora, tu respuesta es casi ilegible. –

+1

La respuesta también contiene varios errores, a saber: ** 1. ** '(pat)' es un grupo de captura; ** 2. ** '(?: Pat)' es un grupo * que no captura, * no una búsqueda negativa como parece estar implicando (eso sería '(?! Pat)'); ** 3. ** '*' es equivalente a '{0,}' en casi todos los sabores de expresiones regulares - la edad no tiene nada que ver con eso; ** 4. ** que el primer '?' Hace que el '' 'anterior sea reacio (no redundante); ** 5. ** '[\ w.]' Es equivalente a '[A-Za-z0-9 _.]' (Es decir, coincide con un carácter de palabra * o un punto *, no * seguido de un punto *, como dijiste. –

2

Nota: Ahora noto que esta respuesta puede estar un poco fuera de alcance. Aún lo dejaré para obtener más información, pero si crees que está demasiado fuera de alcance, solo comenta y lo eliminaré.


@arnaud es correcto, es para obtener la versión. Here is the code donde se utiliza la expresión:

uaMatch: function(ua) { 
    ua = ua.toLowerCase(); 

    var match = rwebkit.exec(ua) || 
       ropera.exec(ua) || 
       rmsie.exec(ua) || 
       ua.indexOf("compatible") < 0 && rmozilla.exec(ua) || 
       []; 

    return { browser: match[1] || "", version: match[2] || "0" }; 
}, 

Se puede ver que la función devuelve la versión si se detectan y 0 si no. Esto podría ser necesario para algunos navegadores o simplemente se proporciona como información adicional para los desarrolladores.

La función se llama here:

browserMatch = jQuery.uaMatch(userAgent); 
if (browserMatch.browser) { 
    jQuery.browser[ browserMatch.browser ] = true; 
    jQuery.browser.version = browserMatch.version; 
} 
Cuestiones relacionadas