Как заменить все вхождения строки в JavaScript - PullRequest
3824 голосов
/ 17 июля 2009

У меня есть эта строка:

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

Doing

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

, кажется, удаляет только первое вхождение abc в приведенной выше строке. Как я могу заменить все его вхождения?

Ответы [ 55 ]

3981 голосов
/ 17 июля 2009
str = str.replace(/abc/g, '');

В ответ на комментарий:

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

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

В ответ на Щелкните комментарий Upvote , вы можете упростить его еще больше:

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

Примечание: Регулярные выражения содержат специальные (мета) символы, и поэтому опасно слепо передавать аргумент в функции find, описанной выше, без предварительной обработки для экранирования этих символов. Об этом говорится в Руководстве JavaScript по регулярным выражениям , в котором представлена ​​следующая служебная функция

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

Таким образом, чтобы сделать вышеуказанную функцию replaceAll() более безопасной, ее можно изменить на следующее, если вы также включите escapeRegExp:

function replaceAll(str, find, replace) {
    return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
2205 голосов
/ 12 июля 2013

Ради полноты, я задумался о том, какой метод я должен использовать для этого. Как правило, есть два способа сделать это, как предлагают другие ответы на этой странице.

Примечание: Как правило, расширение встроенных прототипов в JavaScript обычно не рекомендуется. Я предоставляю в качестве расширений прототипа String просто для иллюстрации, показывая различные реализации гипотетического стандартного метода на встроенном прототипе String.


Реализация на основе регулярных выражений

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

Реализация разделения и объединения (функциональная)

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

Не зная слишком много о том, как регулярные выражения работают за кулисами с точки зрения эффективности, я склонялся к расколу и присоединялся к реализации в прошлом, не задумываясь о производительности. Когда я задумался о том, что было более эффективно и с какой выгодой, я использовал это в качестве предлога для выяснения.

На моем компьютере с Chrome Windows 8 реализация на основе регулярных выражений является самой быстрой , при этом реализация split и join на 53% медленнее . Это означает, что регулярные выражения в два раза быстрее для ввода lorem ipsum, который я использовал.

Проверьте этот бенчмарк , запустив эти две реализации друг против друга.


Как отмечено в комментарии ниже @ThomasLeduc и других, может быть проблема с реализацией на основе регулярных выражений, если search содержит определенные символы, которые зарезервированы как специальные символы в регулярных выражениях . Реализация предполагает, что вызывающая сторона будет экранировать строку заранее или будет передавать только строки без символов в таблице в Регулярные выражения (MDN).

MDN также предоставляет реализацию для экранирования наших строк. Было бы хорошо, если бы это было также стандартизировано как RegExp.escape(str), но, увы, его не существует:

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

Мы могли бы вызвать escapeRegExp в нашей реализации String.prototype.replaceAll, однако я не уверен, насколько это повлияет на производительность (потенциально даже для строк, для которых экранирование не требуется, как для всех буквенно-цифровых строк).

1267 голосов
/ 18 июля 2009

Примечание: не используйте это в реальном коде.

В качестве альтернативы регулярным выражениям для простой литеральной строки, вы можете использовать

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

Общий шаблон

str.split(search).join(replacement)

Раньше это было быстрее в некоторых случаях, чем при использовании replaceAll и регулярных выражений, но в современных браузерах это больше не так. Таким образом, это действительно должно быть использовано только как быстрый взлом, чтобы избежать необходимости экранировать регулярное выражение, а не в реальном коде.

583 голосов
/ 07 мая 2009

Использование регулярного выражения с установленным флагом g заменит все:

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

Смотрите также здесь

96 голосов
/ 12 февраля 2013

Вот функция-прототип строки, основанная на принятом ответе:

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

РЕДАКТИРОВАТЬ

Если ваш find будет содержать специальные символы, вам нужно их избежать:

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

Скрипка: http://jsfiddle.net/cdbzL/

79 голосов
/ 01 марта 2012

Обновление:

Уже несколько поздно для обновления, но так как я просто наткнулся на этот вопрос и заметил, что мой предыдущий ответ не тот, которым я доволен. Поскольку вопрос касался замены одного слова, невероятно, что никто не думал об использовании границ слов (\b)

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

Это простое регулярное выражение, в большинстве случаев избегающее замены частей слов. Тем не менее, тире - все еще считается границей слова. Поэтому в этом случае можно использовать условные выражения, чтобы избежать замены строк, таких как 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"

По сути, этот вопрос такой же, как и здесь: Javascript заменяет "'" на "' '"

@ Майк, проверь ответ, который я там дал ... Регулярное выражение - не единственный способ заменить несколько вхождений подстроки, это далеко не так. Думай гибко, думай о разделении!

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

В качестве альтернативы, для предотвращения замены частей слова - что будет делать и одобренный ответ! Вы можете обойти эту проблему, используя регулярные выражения, которые, я признаю, несколько более сложны и, как следствие, тоже немного медленнее:

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

Вывод такой же, как принятый ответ, однако с использованием выражения / cat / g в этой строке:

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" ?? 

Ой, действительно, это, вероятно, не то, что вы хотите. Что же тогда? ИМХО, регулярное выражение, которое заменяет только «условно». (то есть не часть слова), например:

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"

Полагаю, это соответствует вашим потребностям. Конечно, это не полная защита, но этого должно быть достаточно, чтобы начать работу. Я бы порекомендовал прочитать еще на этих страницах. Это поможет вам улучшить это выражение для удовлетворения ваших конкретных потребностей.

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

http://www.regular -expressions.info


Окончательное дополнение:

Учитывая, что этот вопрос по-прежнему получает много просмотров, я подумал, что мог бы добавить пример .replace, используемый с функцией обратного вызова. В этом случае это значительно упрощает выражение , а обеспечивает еще большую гибкость, как замена с правильной прописной буквой или замена cat и cats за один раз:

'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
59 голосов
/ 07 мая 2009

Сравнение с глобальным регулярным выражением:

anotherString = someString.replace(/cat/g, 'dog');
41 голосов
/ 17 июля 2009
str = str.replace(/abc/g, '');

Или попробуйте функцию replaceAll отсюда:

Какие полезные методы JavaScript расширяют встроенные объекты?

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

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

РЕДАКТИРОВАТЬ: Разъяснения о заменеВсе наличие

Метод replaceAll добавлен в прототип String. Это означает, что он будет доступен для всех строковых объектов / литералов.

Е.Г.

var output = "test this".replaceAll('this', 'that');  //output is 'test that'.
output = output.replaceAll('that', 'this'); //output is 'test this'
36 голосов
/ 25 марта 2019

Это наиболее распространенные и читаемые методы.

var str = "Test abc test test abc test test test abc test test abc"

Метод-01:

str = str.replace(/abc/g, "replaced text");

Метод-02:

str = str.split("abc").join("replaced text");

Метод-03:

str = str.replace(new RegExp("abc", "g"), "replaced text");

Метод-04:

while(str.includes("abc")){
    str = str.replace("abc", "replaced text");
}

Выход:

console.log(str);
// Test replaced text test test replaced text test test test replaced text test test replaced text
35 голосов
/ 10 сентября 2016

Скажем, вы хотите заменить все 'abc' на '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

Я пытался придумать что-то более простое, чем модификация прототипа строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...