expresiones - Cambio de cadena insensible a las mayúsculas y minúsculas en JavaScript?
replace javascript expresiones regulares (7)
Necesito resaltar, caso insensible, palabras clave dadas en una cadena de JavaScript.
Por ejemplo:
-
highlight("foobar Foo bar FOO", "foo")
debería devolver"<b>foo</b>bar <b>Foo</b> bar <b>FOO</b>"
Necesito que el código funcione para cualquier palabra clave y, por lo tanto, usar una expresión regular codificada como /foo/i
no es una solución suficiente.
¿Cuál es la forma más fácil de hacer esto?
(Esta es una instancia de un problema más general detallado en el título, pero creo que es mejor abordarlo con un ejemplo concreto y útil).
¿Por qué no simplemente crear una nueva expresión regular en cada llamada a su función? Puedes usar:
new Regex([pat], [flags])
donde [pat] es una cadena para el patrón, y [banderas] son las banderas.
¿Qué tal algo así?
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");
Las expresiones regulares están bien, siempre y cuando las palabras clave sean realmente palabras, puedes usar un constructor RegExp en lugar de un literal para crear uno a partir de una variable:
var re= new RegExp(''(''+word+'')'', ''gi'');
return s.replace(re, ''<b>$1</b>'');
La dificultad surge si las palabras clave pueden tener 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 se puede estar completamente seguro de qué personajes necesitan escapar, ya que no se garantiza que la implementación de expresiones regulares de todos los navegadores sea exactamente la misma. (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.
Entonces, lo mejor que puedes hacer es uno de los siguientes:
- intentando atrapar a cada personaje especial en el uso común del navegador hoy [agregar: ver la receta de Sebastian]
- barra invertida: escapa a todos los no alfanuméricos. care: / W también coincidirá con caracteres Unicode no ASCII, que realmente no desea.
- solo asegúrese de que no haya caracteres no alfanuméricos en la palabra clave antes de buscar
Sin embargo, si está usando esto para resaltar palabras en HTML que ya tienen marcado, tiene problemas. Su ''palabra'' puede aparecer en un nombre de elemento o en un valor de atributo, en cuyo caso intentar envolver una <b> alrededor de ella 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.
Para aquellos pobres con disregexia o regexofobia:
function replacei(str, sub, f){
let A = str.toLowerCase().split(sub.toLowerCase());
let B = [];
let x = 0;
for (let i = 0; i < A.length; i++) {
let n = A[i].length;
B.push(str.substr(x, n));
if (i < A.length-1)
B.push(f(str.substr(x + n, sub.length)));
x += n + sub.length;
}
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>.
Puede mejorar el objeto RegExp con una función que le permita escapar de caracteres especiales:
RegExp.escape = function(str)
{
var specials = /[.*+?|()/[/]{}//$^]/g; // .*+?|()[]{}/$^
return str.replace(specials, "//$&");
}
Entonces, usted podría usar lo que los demás sugirieron sin preocupaciones:
function highlightWordsNoCase(line, word)
{
var regex = new RegExp("(" + RegExp.escape(word) + ")", "gi");
return line.replace(regex, "<b>$1</b>");
}
Puede usar expresiones regulares si prepara la cadena de búsqueda. En PHP, por ejemplo, hay una función preg_quote, que reemplaza todos los regex-chars en una cadena con sus versiones de escape.
Aquí está tal función para 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/ )
Entonces puedes hacer lo siguiente:
function highlight( data, search )
{
return data.replace( new RegExp( "(" + preg_quote( search ) + ")" , ''gi'' ), "<b>$1</b>" );
}
function highlightWords( line, word )
{
var regex = new RegExp( ''('' + word + '')'', ''gi'' );
return line.replace( regex, "<b>$1</b>" );
}