2009-08-21 19 views
6

¿Cómo puedo emular la palabra clave SQL LIKE en JavaScript?Emulación de SQL LIKE en JavaScript

Para aquellos de ustedes que no saben lo que LIKE Es decir, es una expresión regular muy simple que sólo es compatible con los comodines %, que coincide con 0 o más caracteres, y _, que coincide exactamente un caracter.

Sin embargo, no es sólo posible hacer algo como:

var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null; 

... porque el patrón puede contener puntos, estrellas y otros caracteres especiales de expresiones regulares.

+0

FYI- en su código de ejemplo que se está perdiendo un paréntesis de cierre antes " '.exec'" – Kip

+0

@ C.ba rlow: no dude en eliminar las marcas antiguas de 'edit: .. blah' cuando edite.Apunta a "la mejor pregunta independiente"; el historial de edición está ahí para que todos lo vean, por lo que no es necesario mantener el comentario. :) – sarnold

+0

@sarnold Gotcha! Gracias por la guía! –

Respuesta

6

Lo que tenga funcionará mientras escape por primera vez los caracteres de la expresión regular en su patrón. A continuación se muestra un ejemplo de Simon Willison’s blog:

RegExp.escape = function(text) { 
    if (!arguments.callee.sRE) { 
    var specials = [ 
     '/', '.', '*', '+', '?', '|', 
     '(', ')', '[', ']', '{', '}', '\\' 
    ]; 
    arguments.callee.sRE = new RegExp(
     '(\\' + specials.join('|\\') + ')', 'g' 
    ); 
    } 
    return text.replace(arguments.callee.sRE, '\\$1'); 
} 

A continuación, podría poner en práctica su código como:

likeExpr = RegExp.escape(likeExpr); 
var match = new RegEx(likeExpr.replace("%", ".*").replace("_", ".")).exec(str) != null; 
+1

Asumiendo lo que ya tiene: 'RegExp.like = function (text) {return new RegExp ("^"+ (RegExp.escape (text) .replace (/%/g,". * "). Replace (/ _/g, ".")) + "$"); } 'podría ser un poco más reutilizable para él. – gnarf

+0

Esa implementación de 'Regex.escape' es bastante exagerada. En primer lugar, la aparición 'arguments.callee' impide algunas de las optimizaciones en los navegadores modernos (y está obsoleta en ES5-strict), por lo que es mejor evitarla cuando sea posible. En segundo lugar, hay un escape innecesario de caracteres, cuando en su lugar podrían colocarse en una clase de caracteres. Aquí hay una versión más pequeña (y probablemente más rápida) que usamos en Prototype.js - 'RegExp.escape = function (str) {return str.replace (/ ([. * +?^=!: $ {} () | [\] \/\\])/g, '\\ $ 1'); }; ' – kangax

1

Si desea utilizar una expresión regular, puede ajustar cada carácter de la cadena entre corchetes. Entonces solo tienes unos pocos personajes para escapar.

Pero una mejor opción podría ser truncar las cadenas de destino para que la longitud coincida con su cadena de búsqueda y verificar la igualdad.

2

Aquí es una función que uso, basado en PHP's preg_quote function:

function regex_quote(str) { 
    return str.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1"); 
} 

Por lo que su línea se ahora sea:

var match = new RegEx(regex_quote(likeExpr).replace("%", ".*").replace("_", ".")).exec(str) != null; 
3

que estaba buscando una respuesta a la misma pregunta y se acercó con esto después de leer la respuesta de Kip:

String.prototype.like = function(search) { 
    if (typeof search !== 'string' || this === null) {return false; } 
    // Remove special chars 
    search = search.replace(new RegExp("([\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-])", "g"), "\\$1"); 
    // Replace % and _ with equivalent regex 
    search = search.replace(/%/g, '.*').replace(/_/g, '.'); 
    // Check matches 
    return RegExp('^' + search + '$', 'gi').test(this); 
} 

A continuación, puede utilizar la siguiente manera (tenga en cuenta que no tiene en cuenta mayúsculas/minúsculas):

var url = 'http://www.mydomain.com/page1.aspx'; 
console.log(url.like('%mydomain.com/page_.asp%')); // true 

NOTA 29/11/2013: Actualizado con RegExp.test() mejora en el rendimiento según Lucios comentarios a continuación.

+0

en lugar de !! this.match (..., should not use this.test (...? –

+0

) El método hi @ LucioM.Tato, x.test() es para instancias RegExp, no para String. objeto .. [http://www.w3schools.com/jsref/jsref_regexp_test.asp](http://www.w3schools.com/jsref/jsref_regexp_test.asp) –

+0

Lo siento, no estaba claro. volver a obtener una matriz de coincidencias (regexp cara) en lugar de utilizar .test (mejor rendimiento). Debería ser: devolver nueva prueba RegExp (...). (esto), en lugar de convertir una matriz o nulo en booleano por doble negación. http://stackoverflow.com/questions/10940137/regex-test-vs-string-match-to-know-if-a-string-matches-a-regular-expression –

0

En la respuesta de Chris Van Opstal debe usar replaceAll en lugar de reemplazar para reemplazar todas las apariciones de '%' y '_'. referencia a cómo hacer replaceAll - here

0

Johnny Come Lately aquí, pero esto funciona para mí lo uso para mis páginas de spa para evitar ciertas páginas que muestran resultados después de la página por defecto:

function like(haystack,needle){ 
    needle = needle.split(','); 
    var str = haystack.toLowerCase(); 
    var n = -1; 
    for(var i=0;i<needle.length;i++){ 
     n = str.search(needle[i]); 
     if(n > -1){ 
      return n; 
     } 
    } 
return n; 
} 

uso es - aquí quiero mostrar ningún resultado, no en las herramientas, páginas de contacto o en el hogar - resultados() es una función no muestro aquí:

var n = like($data,'tools,contact,home'); 
//~ alert(n); 
if(n < 0){// does not match anything in the above string 
    results($data); 
}