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


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

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

дела

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

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


3080


источник


Ответы:


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

Заметка: В общем, расширение встроенных прототипов в 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, реализация на основе регулярных выражений является самой быстрой , с разделение и объединение на 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однако я не уверен, насколько это повлияет на производительность (возможно даже для строк, для которых побег не нужен, как и все буквенно-цифровые строки).


1551



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, "\\$1");
}

Поэтому, чтобы сделать replaceAll()выше, чем безопаснее, его можно изменить до следующего, если вы также включите escapeRegExp:

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

3524



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

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

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

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

str.split(search).join(replacement)

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


1185



Using a regular expression with the g flag set will replace all:

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

See here also


493



Here's a string prototype function based on the accepted answer:

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

EDIT

If your find will contain special characters then you need to escape them:

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

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


89



Update:

It's somewhat late for an update, but since I just stumbled on this question, and noticed that my previous answer is not one I'm happy with. Since the question involved replaceing a single word, it's incredible nobody thought of using word boundaries (\b)

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

This is a simple regex that avoids replacing parts of words in most cases. However, a dash - is still considered a word boundary. So conditionals can be used in this case to avoid replacing strings like 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"

basically, this question is the same as the question here: Javascript replace " ' " with " '' "

@Mike, check the answer I gave there... regexp isn't the only way to replace multiple occurrences of a subsrting, far from it. Think flexible, think split!

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

Alternatively, to prevent replacing word parts -which the approved answer will do, too! You can get around this issue using regular expressions that are, I admit, somewhat more complex and as an upshot of that, a tad slower, too:

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

The output is the same as the accepted answer, however, using the /cat/g expression on this string:

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 indeed, this probably isn't what you want. What is, then? IMHO, a regex that only replaces 'cat' conditionally. (ie not part of a word), like so:

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"

My guess is, this meets your needs. It's not fullproof, of course, but it should be enough to get you started. I'd recommend reading some more on these pages. This'll prove useful in perfecting this expression to meet your specific needs.

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

http://www.regular-expressions.info


Final addition:

Given that this question still gets a lot of views, I thought I might add an example of .replace used with a callback function. In this case, it dramatically simplifies the expression and provides even more flexibility, like replacing with correct capitalisation or replacing both cat and cats in one go:

'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

74



Match against a global regular expression:

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

44



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

Or try the replaceAll function from here:

What are useful JavaScript methods that extends built-in objects?

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

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

EDIT: Clarification about replaceAll availability

The 'replaceAll' method is added to String's prototype. This means it will be available for all string objects/literals.

E.g.

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

33



Say you want to replace all the 'abc' with '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

I was trying to think about something more simple than modifying the string prototype.


28



Use a regular expression:

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

26



Replacing single quotes:

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

    return text;
}

24