Pregunta ¿Cómo reemplazar todas las apariciones de una cadena en JavaScript?


Tengo esta cadena:

"Test abc test test abc test test test abc test test abc"

Obra

str = str.replace('abc', '');

parece solo eliminar la primera aparición de abc en la cadena de arriba. ¿Cómo puedo reemplazar todas ocurrencias de eso?


3164
2017-07-17 17:53


origen


Respuestas:


Para completar, comencé a pensar qué método debería usar para hacer esto. Básicamente, hay dos maneras de hacerlo, tal como lo sugieren las otras respuestas en esta página.

Nota: En general, no se recomienda extender los prototipos incorporados en JavaScript. Proporciono extensiones en el prototipo de cadena simplemente para fines de ilustración, que muestran diferentes implementaciones de un método estándar hipotético en el String prototipo incorporado


Implementación basada en expresiones regulares

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

Dividir y unir (Funcional) Implementación

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

Como no sabía demasiado sobre cómo las expresiones regulares funcionan detrás de escena en términos de eficiencia, tendía a inclinarme hacia la división y unirme a la implementación en el pasado sin pensar en el rendimiento. Cuando me pregunté cuál era más eficiente, y con qué margen, lo usé como una excusa para descubrirlo.

En mi máquina Chrome para Windows 8, la implementación basada en expresiones regulares es la más rápida, con el la implementación de split y join es un 53% más lenta. Lo que significa que las expresiones regulares son dos veces más rápidas para la entrada lorem ipsum que utilicé.

Mira esto punto de referencia ejecutando estas dos implementaciones cara a cara.


Como se señala en el comentario más abajo por @ThomasLeduc y otros, podría haber un problema con la implementación basada en expresiones regulares si search contiene ciertos caracteres que están reservados como caracteres especiales en expresiones regulares. La implementación asume que la persona que llama escapará de la cadena de antemano o solo pasará las cadenas que están sin los caracteres en la tabla de Expresiones regulares (MDN).

MDN también proporciona una implementación para escapar de nuestras cadenas. Sería bueno si esto también estuviera estandarizado RegExp.escape(str), pero, por desgracia, no existe:

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

Podríamos llamar escapeRegExp dentro de nuestro String.prototype.replaceAll implementación, sin embargo, no estoy seguro de cuánto afectará esto al rendimiento (potencialmente incluso para cadenas para las cuales no se necesita el escape, como todas las cadenas alfanuméricas).


1627
2017-07-12 01:46



str = str.replace(/abc/g, '');

En respuesta al comentario:

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

En respuesta a Haz clic en Votación a favorComentario de S, usted puede simplificar aún más:

function replaceAll(str, find, replace) {
    return str.replace(new RegExp(find, 'g'), replace);
}

Nota: Las expresiones regulares contienen caracteres especiales (meta), y como tal, es peligroso pasar ciegamente un argumento en el find funcionar arriba sin preprocesarlo para escapar esos caracteres. Esto está cubierto en el Red de desarrolladores Mozillaes Guía de JavaScript sobre expresiones regulares, donde presentan la siguiente función de utilidad:

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

Entonces, para hacer replaceAll() función anterior más segura, podría modificarse a lo siguiente si también incluye escapeRegExp:

function replaceAll(str, find, replace) {
    return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

3586
2017-07-17 17:54



Nota: No use esto en código real.

Como alternativa a las expresiones regulares para una cadena literal simple, podrías usar

str = "Test abc test test abc test...".split("abc").join("");

El patrón general es

str.split(search).join(replacement)

Esto solía ser más rápido en algunos casos que el uso replaceAll y una expresión regular, pero ese ya no parece ser el caso en los navegadores modernos. Por lo tanto, esto solo debería usarse realmente como un truco rápido para evitar la necesidad de escapar de la expresión regular, no en el código real.


1193
2017-07-17 20:29



Usando una expresión regular con el g el conjunto de banderas reemplazará a todo:

someString = 'the cat looks like a cat';
anotherString = someString.replace(/cat/g, 'dog');
// anotherString now contains "the dog looks like a dog"

Vea aquí también


505
2018-05-06 23:18



Aquí hay una función de prototipo de cadena basada en la respuesta aceptada:

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find, 'g'), replace);
};

EDITAR 

Si tu find contendrá caracteres especiales y luego tendrá que escapar de ellos:

String.prototype.replaceAll = function (find, replace) {
    var str = this;
    return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
};

Violín: http://jsfiddle.net/cdbzL/


90
2018-02-11 23:03



Actualizar:

Es algo tarde para una actualización, pero desde que me encontré con esta pregunta, y noté que mi respuesta anterior no es con la que estoy contento. Como la pregunta consistía en reemplazar una sola palabra, es increíble que a nadie se le haya ocurrido usar límites de palabras (\b)

'a cat is not a caterpillar'.replace(/\bcat\b/gi,'dog');
//"a dog is not a caterpillar"

Esta es una expresión regular simple que evita reemplazar partes de palabras en la mayoría de los casos. Sin embargo, un guion - todavía se considera un límite de palabras. Entonces, los condicionales se pueden usar en este caso para evitar reemplazar cadenas como cool-cat:

'a cat is not a cool-cat'.replace(/\bcat\b/gi,'dog');//wrong
//"a dog is not a cool-dog" -- nips
'a cat is not a cool-cat'.replace(/(?:\b([^-]))cat(?:\b([^-]))/gi,'$1dog$2');
//"a dog is not a cool-cat"

Básicamente, esta pregunta es la misma que aquí: Javascript reemplaza "'" por "' '"

@Mike, verifique la respuesta que di allí ... la expresión regular no es la única forma de reemplazar múltiples ocurrencias de una subserie, ni mucho menos. ¡Piensa flexible, piensa dividido!

var newText = "the cat looks like a cat".split('cat').join('dog');

Alternativamente, para evitar reemplazar partes de palabras, ¡lo cual también será la respuesta aprobada! Puede solucionar este problema utilizando expresiones regulares que, reconozco, son algo más complejas y, como resultado, un poco más lentas también:

var regText = "the cat looks like a cat".replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");

El resultado es el mismo que la respuesta aceptada, sin embargo, usando la expresión / cat / g en esta cadena:

var oops = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/cat/g,'dog');
//returns "the dog looks like a dog, not a dogerpillar or cooldog" ?? 

Oops de hecho, esto probablemente no es lo que quieres. ¿Que es entonces? En mi humilde opinión, una expresión regular que solo reemplaza 'gato' condicionalmente. (es decir, no forma parte de una palabra), así:

var caterpillar = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");
//return "the dog looks like a dog, not a caterpillar or coolcat"

Supongo que esto satisface tus necesidades. No es a prueba de todo, por supuesto, pero debería ser suficiente para comenzar. Recomiendo leer un poco más en estas páginas. Esto será útil para perfeccionar esta expresión y satisfacer sus necesidades específicas.

http://www.javascriptkit.com/jsref/regexp.shtml

http://www.regular-expressions.info


Además final:

Dado que esta pregunta aún recibe muchas opiniones, pensé que podría agregar un ejemplo de .replace usado con una función de devolución de llamada. En este caso, simplifica dramáticamente la expresión y proporciona aún más flexibilidad, como reemplazar con mayúsculas o reemplazar ambas cat y cats en una ida:

'Two cats are not 1 Cat! They\'re just cool-cats, you caterpillar'
   .replace(/(^|.\b)(cat)(s?\b.|$)/gi,function(all,char1,cat,char2)
    {
       //check 1st, capitalize if required
       var replacement = (cat.charAt(0) === 'C' ? 'D' : 'd') + 'og';
       if (char1 === ' ' && char2 === 's')
       {//replace plurals, too
           cat = replacement + 's';
       }
       else
       {//do not replace if dashes are matched
           cat = char1 === '-' || char2 === '-' ? cat : replacement;
       }
       return char1 + cat + char2;//return replacement string
    });
//returns:
//Two dogs are not 1 Dog! They're just cool-cats, you caterpillar

75
2018-03-01 10:02



Coincidencia con una expresión regular global:

anotherString = someString.replace(/cat/g, 'dog');

45
2018-05-06 23:23



str = str.replace(/abc/g, '');

O pruebe la función replaceAll desde aquí:

¿Cuáles son los métodos de JavaScript útiles que amplían los objetos incorporados?

str = str.replaceAll('abc', ''); OR

var search = 'abc';
str = str.replaceAll(search, '');

EDITAR: Aclaración sobre reemplazarToda disponibilidad

El método 'replaceAll' se agrega al prototipo de String. Esto significa que estará disponible para todos los objetos / literales de cadenas.

P.ej.

var output = "test this".replaceAll('this', 'that');  //output is 'test that'.
output = output.replaceAll('that', 'this'); //output is 'test this'

34
2017-07-17 17:55



Digamos que quiere reemplazar todo el 'abc' por 'x':

let some_str = 'abc def def lom abc abc def'.split('abc').join('x')
console.log(some_str) //x def def lom x x def

Estaba tratando de pensar en algo más simple que modificar el prototipo de cuerda.


29
2017-09-10 14:59



Use una expresión regular:

str.replace(/abc/g, '');

27
2017-07-17 17:56