2008-11-11 16 views
50

Necesito resaltar, sin distinción de mayúsculas/minúsculas, palabras clave dadas en una cadena de JavaScript.Sustitución de cadenas insensible a mayúsculas y minúsculas en JavaScript?

Por ejemplo:

  • highlight("foobar Foo bar FOO", "foo") deberían volver "<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"

necesito el código para trabajar para cualquier palabra clave, y por lo tanto usando una expresión regular codificado como /foo/i no es una solución suficiente.

¿Cuál es la manera más fácil de hacer esto?

(Este un ejemplo de un problema más general detallado en el título, pero siento que es mejor para hacer frente con un ejemplo concreto y útil).

Respuesta

67

Usted puede expresiones uso regular si se prepara la búsqueda cuerda. En PHP, p. hay una función preg_quote, que reemplaza todos los regex-chars en una cadena con sus versiones de escape.

Aquí es una función de este tipo de javascript:

function preg_quote(str) { 
    // http://kevin.vanzonneveld.net 
    // + original by: booeyOH 
    // + improved by: Ates Goral (http://magnetiq.com) 
    // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 
    // + bugfixed by: Onno Marsman 
    // *  example 1: preg_quote("$40"); 
    // *  returns 1: '\$40' 
    // *  example 2: preg_quote("*RRRING* Hello?"); 
    // *  returns 2: '\*RRRING\* Hello\?' 
    // *  example 3: preg_quote("\\.+*?[^]$(){}=!<>|:"); 
    // *  returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:' 

    return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1"); 
} 

(Tomado de http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_preg_quote/)

Por lo que se desvivían por hacer lo siguiente:

function highlight(data, search) 
{ 
    return data.replace(new RegExp("(" + preg_quote(search) + ")" , 'gi'), "<b>$1</b>"); 
} 
+0

No creo que el ejemplo funciona. – tvanfosson

+0

Veo, solo se reemplaza la primera ocurrencia. No sabía que reemplazar se comporta así. El preg_quote es importante si quiere resaltar cadenas con/o * u otros caracteres de expresiones regulares. – okoman

+0

Um .. it * is * javascript. Acabo de decir que hay una función en PHP llamada preg_quote. Luego incluí una versión js de esa función y una función js ... estos ejemplos de código * son * js – okoman

0

¿Por qué no crear una nueva expresión regular en cada llamada a su función? Puede usar:

new Regex([pat], [flags]) 

donde [pat] es una cadena para el patrón, y [flags] son ​​las banderas.

63
function highlightWords(line, word) 
{ 
    var regex = new RegExp('(' + word + ')', 'gi'); 
    return line.replace(regex, "<b>$1</b>"); 
} 
+1

Por supuesto, debe tener cuidado con lo que está reemplazando y lo que está buscando como notas @bobince . Lo anterior funcionará bien para texto sin formato y la mayoría de las búsquedas si tiene cuidado de citar sus caracteres regex ... – tvanfosson

+1

exactamente lo que necesitaba :) thx – daniellmb

+0

Esto tendrá problemas si hay caracteres regex en la palabra que se reemplaza. La solución de @ okoman lo soluciona. –

5

Las expresiones regulares son bien siempre y cuando las palabras clave son realmente palabras, sólo puede utilizar un constructor RegExp en lugar de un literal para crear uno de una variable:

var re= new RegExp('('+word+')', 'gi'); 
return s.replace(re, '<b>$1</b>'); 

La dificultad surge si 'palabras clave 'puede tener signos de puntuación, ya que la puntuación tiende a tener un significado especial en las expresiones regulares. Desafortunadamente, a diferencia de la mayoría de los otros lenguajes/bibliotecas con compatibilidad con expresiones regulares, no existe una función estándar para evitar la puntuación de las expresiones regulares en JavaScript.

Y no puede estar completamente seguro de qué caracteres necesitan escaparse, ya que no todas las implementaciones del navegador de expresiones regulares están garantizadas para ser exactamente iguales. (En particular, los navegadores más nuevos pueden agregar nuevas funcionalidades). Y los caracteres que escapan de la barra invertida que no son especiales no se garantiza que funcionen todavía, aunque en la práctica sí lo hace.

Así que lo mejor que puede hacer es uno de:

  • intentar coger cada carácter especial en el uso común del navegador de hoy [Añadir: véase la receta de Sebastian]
  • barra invertida-escapar de todos los no-alfanuméricos. care: \ W también coincidirá con caracteres Unicode no ASCII, que realmente no desea.
  • Sólo hay que asegurarse de que no existen los no alfanuméricos en la palabra clave antes de buscar

Si está usando este para resaltar las palabras en HTML que ya tiene marcado en, problema, sin embargo, lo que tienes. Su 'palabra' puede aparecer en un nombre de elemento o valor de atributo, en cuyo caso intentar envolver un < b> alrededor causará daños. En escenarios más complicados, posiblemente incluso una inyección HTML al agujero de seguridad XSS. Si tiene que lidiar con el marcado, necesitará un enfoque más complicado, dividiendo el marcado '< ...>' antes de intentar procesar cada tramo de texto por sí mismo.

13

Se puede mejorar el objeto RegExp con una función que hace carácter especial escape para usted:

RegExp.escape = function(str) 
{ 
    var specials = /[.*+?|()\[\]{}\\$^]/g; // .*+?|()[]{}\$^ 
    return str.replace(specials, "\\$&"); 
} 

allí tendría que ser capaz de utilizar lo que sugerían los demás sin ningún tipo de preocupaciones:

function highlightWordsNoCase(line, word) 
{ 
    var regex = new RegExp("(" + RegExp.escape(word) + ")", "gi"); 
    return line.replace(regex, "<b>$1</b>"); 
} 
+0

? en javascript RegExp necesita ser escapado con doble barra diagonal inversa como \\? – Jerinaw

+0

@Jerinaw ¿Qué crees que hace mi función 'RegExp.escape'? – Tomalak

+0

http://stackoverflow.com/questions/889957/escaping-question-mark-in-regex-javascript He tenido problemas donde el signo de interrogación necesitaba ser escapado con el doble \ pero supongo que en [] no lo haces Necesito escapar de eso. – Jerinaw

4

¿Qué pasa con algo como esto:

if(typeof String.prototype.highlight !== 'function') { 
    String.prototype.highlight = function(match, spanClass) { 
    var pattern = new RegExp(match, "gi"); 
    replacement = "<span class='" + spanClass + "'>$&</span>"; 

    return this.replace(pattern, replacement); 
    } 
} 

Esto podría llamarse así:

var result = "The Quick Brown Fox Jumped Over The Lazy Brown Dog".highlight("brown","text-highlight"); 
1

Para los pobres con disregexia o regexophobia:

function replacei(str, sub, f){ 
 
\t let A = str.toLowerCase().split(sub.toLowerCase()); 
 
\t let B = []; 
 
\t let x = 0; 
 
\t for (let i = 0; i < A.length; i++) { 
 
\t \t let n = A[i].length; 
 
\t \t B.push(str.substr(x, n)); 
 
\t \t if (i < A.length-1) 
 
\t \t \t B.push(f(str.substr(x + n, sub.length))); 
 
\t \t x += n + sub.length; 
 
\t } 
 
\t return B.join(''); 
 
} 
 

 
s = 'Foo and FOO (and foo) are all -- Foo.' 
 
t = replacei(s, 'Foo', sub=>'<'+sub+'>') 
 
console.log(t)

Salida:

<Foo> and <FOO> (and <foo>) are all -- <Foo>. 
Cuestiones relacionadas