Как заменить все вхождения строки в JavaScript

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

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

Выполнение

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

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

3679
17 июля '09 в 20:53
источник поделиться
53 ответов
  • 1
  • 2

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

Примечание: В общем, расширение встроенных прототипов в 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, который я использовал.

Проверьте benchmark, выполнив эти две реализации друг против друга.


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

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

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

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

2094
12 июля '13 в 4:46
источник
str = str.replace(/abc/g, '');

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

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

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

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

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

Примечание.. Регулярные выражения содержат специальные (мета) символы и, как таковые, опасно слепо передать аргумент в функции find выше, не предварительно обработав его, чтобы избежать этих символов. Это описано в Mozilla Developer Network Руководство по регулярным выражениям 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);
}
3897
17 июля '09 в 20:54
источник

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

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

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

Общий шаблон

str.split(search).join(replacement)

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

1256
17 июля '09 в 23:29
источник

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

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

См. также

564
07 мая '09 в 2:18
источник

Здесь строковая прототипная функция, основанная на принятом ответе:

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

EDIT

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

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

Fiddle: http://jsfiddle.net/cdbzL/

94
12 февр. '13 в 2:03
источник

Обновить:

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

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

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

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

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

На самом деле, это, вероятно, не то, что вы хотите. Что же тогда? IMHO, регулярное выражение, которое заменяет "cat" условно. (т.е. не является частью слова), например:

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
77
01 марта '12 в 13:02
источник

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

anotherString = someString.replace(/cat/g, 'dog');
58
07 мая '09 в 2:23
источник
str = str.replace(/abc/g, '');

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

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

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

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

РЕДАКТИРОВАТЬ: Разъяснение относительно доступности replaceAll

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

например.

var output = "test this".replaceAll('this', 'that');  //output is 'test that'.
output = output.replaceAll('that', 'this'); //output is 'test this'
39
17 июля '09 в 20:55
источник

Предположим, вы хотите заменить все "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

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

34
10 сент. '16 в 17:59
источник

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

str.replace(/abc/g, '');
32
17 июля '09 в 20:56
источник

Замена одиночных кавычек:

function JavaScriptEncode(text){
    text = text.replace(/'/g,''')
    // More encode here if required

    return text;
}
30
20 июня '15 в 0:24
источник

Использование RegExp в JavaScript может сделать всю работу за вас, просто сделайте что-то вроде ниже, не забывайте /g после которого выделяется глобальное:

var str ="Test abc test test abc test test test abc test test abc";
str = str.replace(/abc/g, '');

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

String.prototype.replaceAll = String.prototype.replaceAll || function(string, replaced) {
  return this.replace(new RegExp(string, 'g'), replaced);
};

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

var str ="Test abc test test abc test test test abc test test abc";
str = str.replaceAll('abc', '');

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

26
06 июня '17 в 16:39
источник

//зацикливать его до появления числа в 0. ИЛИ просто скопировать/вставить

    function replaceAll(find, replace, str) 
    {
      while( str.indexOf(find) > -1)
      {
        str = str.replace(find, replace);
      }
      return str;
    }
23
05 июня '13 в 7:57
источник
str = str.replace(new RegExp("abc", 'g'), "");

работал лучше для меня, чем вышеупомянутые ответы. поэтому new RegExp("abc", 'g') создает RegExp, что соответствует всему присутствию (флаг 'g') текста ("abc"). Вторая часть - это то, что заменяется на, в вашем случае пустую строку (""). str - это строка, и мы должны ее переопределить, так как replace(...) просто возвращает результат, но не переопределяет. В некоторых случаях вы можете использовать это.

22
28 дек. '17 в 15:27
источник

Это самая быстрая версия, которая не использует регулярные выражения.

Пересмотренный jsperf

replaceAll = function(string, omit, place, prevstring) {
  if (prevstring && string === prevstring)
    return string;
  prevstring = string.replace(omit, place);
  return replaceAll(prevstring, omit, place, string)
}

Это почти дважды так же быстро, как метод split и join.

Как указано в комментарии здесь, это не будет работать, если ваша переменная omit содержит place, как в: replaceAll("string", "s", "ss"), потому что она всегда сможет заменить другое вхождение этого слова.

Существует еще один jsperf с вариантами на моей рекурсивной замене, которые идут еще быстрее (http://jsperf.com/replace-all-vs-split-join/12)!

  • Обновление 27 июля 2017 года. Похоже, что RegExp теперь имеет самую быструю производительность в недавно выпущенном Chrome 59.
22
04 апр. '14 в 21:49
источник

Если то, что вы хотите найти, уже находится в строке, и у вас нет регулярного выражения escaper, вы можете использовать join/split:

    function replaceMulti(haystack, needle, replacement)
    {
        return haystack.split(needle).join(replacement);
    }

    someString = 'the cat looks like a cat';
    console.log(replaceMulti(someString, 'cat', 'dog'));
18
20 июня '13 в 2:21
источник
function replaceAll(str, find, replace) {
  var i = str.indexOf(find);
  if (i > -1){
    str = str.replace(find, replace); 
    i = i + replace.length;
    var st2 = str.substring(i);
    if(st2.indexOf(find) > -1){
      str = str.substring(0,i) + replaceAll(st2, find, replace);
    }       
  }
  return str;
}
17
29 сент. '14 в 22:12
источник

Мне нравится этот метод (он выглядит немного чище):

text = text.replace(new RegExp("cat","g"), "dog"); 
14
15 мая '13 в 17:03
источник
var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/

12
04 сент. '13 в 13:01
источник
while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}
12
29 апр. '14 в 13:25
источник

Если строка содержит аналогичный шаблон, такой как abccc, вы можете использовать это:

str.replace(/abc(\s|$)/g, "")
12
07 окт. '17 в 23:56
источник

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

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
11
25 марта '19 в 12:38
источник

Предыдущие ответы слишком сложны. Просто используйте функцию замены следующим образом:

str.replace(/your_regex_pattern/g, replacement_string);

Пример:

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

var res = str.replace(/[abc]+/g, "");

console.log(res);
11
23 окт. '18 в 12:34
источник

Просто следуйте этому регулярному выражению oneliner, добавляя чувствительность к регистру, поэтому, если вы делаете "ABC", он будет действовать так же, как и для "abc".

str = str.replace(/abc/gi, "");
9
17 сент. '18 в 15:58
источник

Если вы пытаетесь убедиться, что строка, которую вы ищете, не будет существовать даже после замены, вам нужно использовать цикл.

Например:

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

Когда вы закончите, у вас все равно будет "test abc"!

Самый простой цикл для решения этого вопроса:

var str = 'test aabcbc';
while (str != str.replace(/abc/g, '')){
   str.replace(/abc/g, '');
}

Но это запустит замену дважды для каждого цикла. Возможно (рискуя проголосовать), которые могут быть объединены для немного более эффективной, но менее читаемой формы:

var str = 'test aabcbc';
while (str != (str = str.replace(/abc/g, ''))){}
// alert(str); alerts 'test '!

Это может быть особенно полезно при поиске повторяющихся строк.
Например, если у нас есть "a,, b", и мы хотим удалить все дубликаты запятых.
[В этом случае можно было бы сделать .replace(/, +/g, ','), но в какой-то момент регулярное выражение становится сложным и достаточно медленным, чтобы зацикливаться.]

9
28 сент. '14 в 22:58
источник

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

//Consider below example
originalString.replace(/stringToBeReplaced/gi, '');

//Output will be all the occurrences removed irrespective of casing.

Вы можете сослаться на подробный пример здесь.

9
03 мая '16 в 21:39
источник
var string  = 'Test abc Test abc Test abc Test abc'
string = string.replace(/abc/g, '')
console.log(string)
8
09 марта '18 в 12:41
источник

Вы можете просто использовать ниже метод

/**
 * Replace all the occerencess of $find by $replace in $originalString
 * @param  {originalString} input - Raw string.
 * @param  {find} input - Target key word or regex that need to be replaced.
 * @param  {replace} input - Replacement key word
 * @return {String}       Output string
 */
function replaceAll(originalString, find, replace) {
  return originalString.replace(new RegExp(find, 'g'), replace);
};
7
15 февр. '16 в 15:05
источник

Просто добавьте /g

document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');

к

// Replace 'hello' string with /hello/g regular expression.
document.body.innerHTML = document.body.innerHTML.replace(/hello/g, 'hi');

/g означает глобальный

7
05 июня '15 в 10:16
источник

Вы можете попробовать объединить эти два мощных метода.

"test abc test test abc".split("abc").join("")

Надеюсь, поможет!

7
09 окт. '13 в 18:04
источник
  • 1
  • 2

Посмотрите другие вопросы по меткам или Задайте вопрос