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

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

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

делаешь

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

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

30 ответов


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

Примечание: В общем, расширение встроенных прототипов в JavaScript, как правило, не рекомендуется. Я предоставляю в качестве расширений прототип строки просто для иллюстрации, показывая различные реализации гипотетического стандартного метода на 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,реализация на основе регулярных выражений является самой быстрой С разделить и присоединиться к реализации на 53% медленнее. Это означает, что регулярные выражения в два раза быстрее для входа lorem ipsum, который я использовал.

зацените benchmark запуск этих двух реализаций друг против друга.


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

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

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

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


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 функция выше без предварительной обработки, чтобы избежать этих символов. Это покрыто в Сеть Разработчиков Mozilla ' s в JavaScript Руководство по регулярным выражениям, где они представляют следующую функцию утилиты:

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

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

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

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

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

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

общая картина

str.split(search).join(replacement)

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


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

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

посмотреть здесь


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

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/


обновление:

несколько поздно для обновления, но так как я только что наткнулся на этот вопрос и заметил, что мой предыдущий ответ не тот, которым я доволен. Поскольку вопрос заключался в замене одного слова, невероятно, что никто не думал об использовании границ слов (\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,'dog');
//"a dog is not a cool-cat"

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

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

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,"dog");

вывод такой же, как и принятый ответ, однако, используя выражение /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,"dog");
//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

матч против глобального регулярного выражения:

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

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

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

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

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

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

EDIT: уточнение о доступности replaceAll

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

Э. Г.

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

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

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


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

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

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

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

    return text;
}

//цикл, пока число вхождений не достигнет 0. Или просто скопируйте / вставьте

    function replaceAll(find, replace, str) 
    {
      while( str.indexOf(find) > -1)
      {
        str = str.replace(find, replace);
      }
      return str;
    }

это быстрый версия не использует регулярные выражения.

пересмотрен см. Этот тест 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.

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

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


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;
}

Если то, что вы хотите найти, уже находится в строке, и у вас нет эскейпера регулярных выражений, вы можете использовать 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'));

var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/


while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}

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

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', '');

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


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

text = text.replace(new RegExp("cat","g"), "dog"); 

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

str.replace(/abc(\s|$)/g, "")

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

например:

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

по завершении у вас все равно будет "тест 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", и мы хотим удалить все дубликаты запятых.
- "В таком случае, можно.замените (/,+/g,','), но в какой-то момент регулярное выражение становится сложным и достаточно медленным для цикла.]


var string  = 'Test abc Test abc Test abc Test abc'
string = string.replace(/abc/g, '')
console.log(string)

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

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

надеюсь, что это помогает!


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

/**
 * 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);
};

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

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

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

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


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

str = str.replace(/abc/gi, "");

просто добавить /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 глобальные


следующая функция работает для меня:

String.prototype.replaceAllOccurence = function(str1, str2, ignore) 
{
    return this.replace(new RegExp(str1.replace(/([\/\,\!\\^$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/$/g,"$$$$"):str2);
} ;

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

"you could be a Project Manager someday, if you work like this.".replaceAllOccurence ("you", "I");

просто скопируйте и вставьте этот код в консоль браузера для тестирования.


Я использую p сохранить результат от предыдущей замены рекурсии:

function replaceAll(s, m, r, p) {
    return s === p || r.contains(m) ? s : replaceAll(s.replace(m, r), m, r, s);
}

он заменит все вхождения в строке s пока это возможно:

replaceAll('abbbbb', 'ab', 'a') → 'abbbb' → 'abbb' → 'abb' → 'ab' → 'a'

чтобы избежать бесконечного цикла, я проверяю, если замена r содержится матча m:

replaceAll('abbbbb', 'a', 'ab') → 'abbbbb'