Як замінити всі входження рядка?


4377

У мене є цей рядок:

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

Виконуємо:

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

здається, видаляє лише перше виникнення abcв рядку вище.

Як я можу замінити всі його випадки?


5
Який ви очікуєте, замінюючи всі події abaв ababaна ca, який результат ви очікуєте? caba? abca? cca?
reinierpost

String.prototype.replaceAll()постачається в Safari 13.1 і тепер знаходиться в Firefox Nightly та Chrome Dev і Canary, а також постачається в Firefox 77 і Chrome 85. Це ще не зафіксовано в MDN, але github.com/tc39/proposed-string-replaceall#high-level-api має пояснювач: "Якщо searchValue - це рядок, він String.prototype.replaceAllзамінює всі входження в searchValue (як би було .split(searchValue).join(replaceValue)використано глобальний & правильно уникнути регулярний вираз). Якщо searchValue є неглобальним регулярним виразом, String.prototype.replaceAllвикидає виняток »
sideshowbarker

Відповіді:


1608

Примітка. Не використовуйте це у критичному коді для виконання.

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

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

Загальна закономірність така

str.split(search).join(replacement)

У деяких випадках це було швидше, ніж використання replaceAllта регулярний вираз, але, здається, це вже не так у сучасних браузерах.

Орієнтир: https://jsperf.com/replace-all-vs-split-join

Висновок: Якщо у вас є випадок, що стосується ефективності використання (наприклад, обробка сотень рядків), використовуйте метод Regexp. Але для більшості типових випадків використання не варто турбуватися про особливі символи.


147
Це мене здивувало, тому що я б очікував, що цей метод буде виділяти більше об'єктів, створювати більше сміття і, таким чином, забирати більше часу, але коли я насправді тестував у браузері, цей метод був стабільно приблизно на 20% швидшим, ніж прийнятий відповідь. Результати, звичайно, можуть відрізнятися.
MgSam

42
Мені було цікаво, і налаштував це: jsperf.com/replace-all-vs-split-join . Здається, що v8 просто божевільний при розщепленні / приєднанні масивів порівняно з іншими двигунами javascript.
fabi

8
Дуже приємно - також позбавляє вас від можливості поганих RegExps при передачі спеціальних символів. Я додаю загальний прапор для "знайти це і заміни" у властивості об'єкта, але був стурбований, чи потрібно мені замінити ". або "}" і забув, що використовував RegEx через 3 місяці!
тобріан

9
І як String.prototype: String.prototype.replaceAll = function(f,r){return this.split(f).join(r);}. Використання: "My string".replaceAll('st', '');виробляє "Моє кільце"
MacroMan

8
Я не бачу причин для попередження не використовувати це у виробництві. Це не більше хака, ніж уникнути регулярного виразу лише тому, що ви хочете замінити кілька випадків, але в першу чергу не потрібен регулярний вираз. Просто ввімкніть цей так званий "хак" в хорошу replaceAllфункцію, і він стане таким же читабельним, як і все інше. Оскільки продуктивність непогана, немає жодних причин уникати цього рішення.
youen

4383
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 Developer Network «s Guide JavaScript на регулярних виразах , де вони представляють наступну функцію корисності (яка змінилася , по крайней мере в два рази , так як ця відповідь була спочатку написано, так що НЕ забудьте перевірити сайт MDN для потенційних оновлень):

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

Отже, щоб зробити replaceAll()функцію вище безпечною, її можна змінити на наступне, якщо ви також включите escapeRegExp:

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

4
Регулярні вирази - це єдиний спосіб досягти цього "поза коробкою", не застосовуючи власний метод "замінити все". Я не пропоную їх використання лише заради їх використання.
Шон Яскравий

10
Це моя власна функція з цього коментаря: function replaceAll(find, replace,str) { var re = new RegExp(find, 'g'); str = str.replace(re, replace); return str; }
Натисніть Upvote

47
Основним застереженням replaceAllреалізації є те, що воно не працюватиме, якщо findмістить метахарактеристики.
Мартін Ендер

1
@SeanBright ти маєш рацію. Я використовував ваш JavaScript у php-коді, тому мені довелося додати додатковий зворотний косий рядок, щоб вийти. Зверху ваш код ідеальний. Я повинен був перевірити. Вибачення jsfiddle.net/7y19xyq8
Onimusha


2437

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

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


8
На Android 4.1 метод regexp швидше на 15%, але ви не уникаєте виразу для пошуку, тому цей орієнтир є неповним.
andreszs

33
Виникає проблема з цим рішенням, якщо в пошуковій рядку, як видається, є спеціальні символи вираження regexp, вони будуть інтерпретовані. Я рекомендую відповідь @Sandy Unitedwolf.
Томас Ледук

2
Перший зробить це так: 'bla.bla'.replaceAll ('. ',' _ '); "_______". Другий з них зробить "bla_bla", що загалом те, що ви хочете зробити.
RobKohr

1
@ThomasLeduc, схоже, проблему, яку ви згадали, можна вирішити за допомогою lodash => lodash.com/docs/4.17.5#escapeRegExp
Метью Бек

1
Залишаючи це тут для майбутніх глядачів, які також цікавляться, чому розширення нативного об’єкта - погана ідея: stackoverflow.com/questions/14034180/…
Бен Купер

690

Використання регулярного виразу з gнабором прапора замінить усіх:

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

Дивіться також тут


15
Я щось дурний, я думаю, але глобальний вираз JS - це єдиний спосіб зробити кілька замін.
Майк

5
Добре технічно ви можете var sourceTextпереглядати кількість примірників ( numOfInstances), використовуючи substringабо розділяючи, і рахувати довжину (серед інших стратегій), thatWhichYouWantToReplaceтоді робити for (var i = 0; i < numOfInstances; i++){ sourceText = sourceText.replace('thatWhichYouWantToReplace', '');} або ще простіше просто скористатися циклом while ( while sourceText.indexOf(thatWhichYouWantToReplace > -1){ sourceText = sourceText.replace(...)), але я не розумію, чому ви хотіли б зробити це так, коли користуватися /gтак просто і, напевно, більш ефективно.
Заргольд

@Zargold Ви хочете зробити цикл, щоб переконатися, що навіть після заміни ви замінили всі екземпляри, що є досить поширеною дією. Дивіться мою відповідь нижче stackoverflow.com/a/26089052/87520
SamGoody

109

Ось функція прототипу рядка на основі прийнятої відповіді:

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/


5
Але що робити, якщо findмістять символи, подібні .або $які мають особливі значення в регулярному вираженні?
callum

1
@callum У цьому випадку вам доведеться уникати змінної пошуку (див. редагування вище).
jesal


jesal, це чудове рішення проблеми із заміною рядків, з якою я стикався, і, очевидно, долає "незмінність" рядків у JavaScript. Чи можете ви чи хтось інший пояснити, як ця прототипна функція перекриває незмінність струн? Це справді працює; Я просто хочу зрозуміти це допоміжне питання, яке воно ставить.
Том

1
@Tom: Це зовсім не долає незмінність: var str = thisстворює друге посилання на незмінну рядок, до якої застосовується replaceметод, що, в свою чергу, повертає нову незмінну рядок . ці прототипні функції повертають нову незмінну рядок, якщо ні, ви зможете написати someStrVar.replaceAll('o', '0');та someStrVarбуде змінено. Натомість вам потрібно написати someStrVar = someStrVar.replaceAll('o', '0');<- reassign, щоб встановити var таким чином, щоб утримувати нову незмінну рядок . не обійтись. Спробуйте в консолі:x = 'foobar'; x.replaceAll('o', '0'); x;
Elias Van Ootegem

87

Оновлення:

Дещо пізно для оновлення, але оскільки я просто спіткнувся з цим питанням і зауважив, що моя попередня відповідь - не одна, якою я задоволений. Оскільки питання стосувалося заміни одного слова, неймовірно, що ніхто не думав використовувати межі слова ( \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');

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

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

Я думаю, що додаткова цікава частина повинна бути розміщена внизу. пс .: Я щойно помітив, що половина першого рядка знаходиться поза зоною, дозвольте це виправити!

69

Збіг проти глобального регулярного вираження:

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

60

Для заміни одноразового використання:

var res = str.replace('abc', "");

Для заміни багаторазового використання:

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

для когось потрібно замінити \ n, ви можете це зробити так:replace(/\n/g, '<br/>')
Фан Ван Лінь

58

Це найпоширеніші і читабельні методи.

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

Спосіб 1:

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

Спосіб 2:

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

Спосіб 3:

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

Спосіб 4:

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

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

Або спробуйте функцію zamjeAll звідси:

Які корисні методи JavaScript розширюють вбудовані об’єкти?

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

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

EDIT: Роз'яснення щодо заміниВсі доступності

До прототипу String додано метод 'zamjeна всі'. Це означає, що він буде доступний для всіх рядкових об'єктів / літералів.

Напр

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

2
Чи можете ви переписати там функцію substituAll () для тих, хто не використовує прототип?
Клацніть Upvote

@Click Upvote .... ви використовуєте прототип, це частина всіх об'єктів JS. Я думаю, ти думаєш про prototype.js бібліотеку JS.
Seth

сет, невелика поправка. Якщо ви додасте метод до прототипу, він доступний для всіх об'єктів цього типу. Метод replceAll був доданий до прототипу String, і він повинен працювати для всіх рядкових об'єктів.
РішенняYogi

@solutionyogi - Так, раніше я використовував прототип (правильно). Я просто звертався до коментаря ОП про "не використання прототипу", який, як я вважав, означає Prototype.js (можливо, неправильно?). Я повинен був сказати "прототип", оскільки я намагався сказати, що об'єкти JavaScript мають прототип. Таким чином, ОП вже "використовувала прототип", хоча і "непрямим" способом. Непрямим може бути неправильний термін вживання тут, але я втомився, так що я не знаю.
Seth

41

Використання 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-коду, якщо ви хочете повторно використовувати.


40

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

Я намагався думати про щось більш просте, ніж модифікацію прототипу рядка.


1
Простий, легкий і, мабуть, найефективніший варіант: приємна відповідь.
machineghost

Насправді, хоча я особисто його не вимірював, розділення / приєднання - це зазвичай дуже ефективне рішення.
машиніст

1
це навіть у хромі, на Firefox на 100% швидше та на IE на 50% повільніше ...: jsperf.com/replace-regex-split-join
Олів'є


32

Заміна одиничних лапок:

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

    return text;
}

2
Як я можу змінити другий рядок для заміни рядків? Це не працює: text = text.replace ('hey', 'hello'); Будь-яка ідея?
Стефан Джорджевич

2
Впевнений Стефан, ось код ... text = text.replace (/ hey / g, 'hello');
Кріс Роузте

26

// циклічно, поки кількість випадків не досягне 0. АБО просто скопіюйте / вставте

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

23
Цей метод небезпечний, не використовуйте його. Якщо рядок заміни містить ключове слово пошуку, то відбудеться нескінченний цикл. Принаймні, зберігайте результат .indexOfу змінній та використовуйте цю змінну як другий параметр .indexOf(мінус довжина ключового слова плюс довжина рядка заміни).
Роб Ш

Я замислююся про те, щоб спочатку замінити шаблон пошуку за допомогою спровокованого символу unicode, про що ми впевнені, що він не використовується у рядку введення. Як і U + E000 в приватній зоні. А потім замініть його до цілі. Я буду це будувати тут. . Я не впевнений, чи це гарна ідея.
Люкс

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

працював для мене краще, ніж наведені вище відповіді. таким чином new RegExp("abc", 'g')створюється RegExp, який відповідає всій появі ( 'g'прапор) тексту ( "abc"). Друга частина - це те, що замінюється, у вашому випадку порожнім рядком ( ""). str- це рядок, і ми повинні його переосмислити, оскільки replace(...)просто повертає результат, але не переосмислює. У деяких випадках ви можете скористатися цим.


Хоча цей фрагмент коду може бути вирішенням, включаючи пояснення, справді допомагає покращити якість вашої публікації. Пам’ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Йіві

Так, ти маєш рацію. додано. також відредагував його, щоб відповісти на початкове запитання :)
csomakk

Примітка: прапор g у регулярному виразі означає, що це глобальний прапор, який відповідатиме всім явищам
першеповідомлення

25

Це найшвидша версія, яка не використовує регулярні вирази .

Переглянуто jsperf

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

Це майже вдвічі швидше, ніж метод розділення та з'єднання.

Як зазначено в коментарі тут, це не працюватиме, якщо ваша omitзмінна містить place, як у:replaceAll("string", "s", "ss") тому що вона завжди зможе замінити інше виникнення слова.

Є інша jsperf з варіантами моєї рекурсивної заміни, які йдуть ще швидше ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • Оновлення 27 липня 2017 року. Схоже, RegExp зараз має найшвидші показники в нещодавно випущеному Chrome 59.

Мені сподобалось ваше рішення ... Я б хотів, щоб я міг вам дати +10, але ось мій +1. Я думаю, що ви можете зберігати індекс підрядків, які були замінені, і переходити до наступного, якщо відповідність знайдена з нижчим індексом, щоб уникнути цієї нескінченної проблеми циклу. Я не можу коментувати виставу, тому що я її не тестував, але це лише мої 2 центи на цю майстерність.
Fr0zenFyr

@ fr0zenfyr, якщо ви хочете перевірити, чи немає пропусків (щоб запобігти нескінченному циклу), ви можете зробити умовне, як if(place.replace(omit) === omit) {немає матчу, тому безпечно використовувати заміну } else {матчу циклу, тому використовуйте інший метод, як розділити та приєднатися}
Коул Лоуренс

Хм .. але в чому сенс поєднання двох рішень? Я так чи інакше не прихильник розбиття / приєднання підходу, все-таки .. дякую за пораду ..
Fr0zenFyr

@ Fr0zenFyr Я вважаю, що метою поєднання двох рішень було б відмовитися від більш повільного методу, якщо ви не можете скористатися більш швидким (наприклад, цикл буде нескінченним). Тож було б надійною охороною, щоб забезпечити функціональність ефективністю, але без можливості виходу з ладу.
Коул Лоуренс

@momomo, як хибно?
SandRock

24

Продуктивність

Сьогодні 27.12.2019 я виконую тести на macOS v10.13.6 (High Sierra) для обраних рішень.

Висновки

  • str.replace(/abc/g, '');( З ) є хорошим крос-браузер швидке рішення для всіх рядків.
  • Рішення на основі split-join( A, B ) або replace( C, D ) швидкі
  • Розчини на основі while( E, F, G, H ) повільні - зазвичай ~ 4 рази повільніше для невеликих струн і приблизно ~ 3000 разів (!) Повільніше для довгих рядків
  • Рішення для повторення ( RA, RB ) повільні і не працюють для довгих рядків

Я також створюю власне рішення. Схоже, зараз це найкоротший, який виконує питання:

str.split`abc`.join``

Деталі

Тести проводили на Chrome 79.0, Safari 13.0.4 та Firefox 71.0 (64 біт). Тести RAта RBвикористання рекурсії. Результати

Введіть тут опис зображення

Коротка рядок - 55 символів

Ви можете запустити тести на своїй машині ТУТ . Результати для Chrome:

Введіть тут опис зображення

Довга рядок: 275 000 символів

Рекурсивні рішення RA і RB дає

RangeError: Максимальний розмір стека викликів перевищено

Для 1М символів вони навіть зламають Chrome

введіть тут опис зображення

Я намагаюся виконувати тести на 1М символів для інших рішень, але E, F, G, H займає стільки часу, що браузер попросить мене розбити сценарій, щоб я зменшив тестову рядок до 275 К символів. Ви можете запустити тести на своїй машині ТУТ . Результати для Chrome

введіть тут опис зображення

Код, який використовується в тестах


1
Тепер це одна пекла глибокої відповіді! Дуже дякую! Хоча, мені цікаво, чому синтаксис "нового RegExp (...)" дає значне вдосконалення.
Márk Gergely

21

Якщо те, що ви хочете знайти, вже є в рядку, і у вас немає підключення регулярного вираження, ви можете використовувати приєднання / розділення:

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

    someString = 'the cat looks like a cat';
    console.log(replaceMulti(someString, 'cat', 'dog'));


Дякую! Це рішення ідеально підходить для моєї проблеми :)
xero399

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

Цікаво, наскільки добре це виконує ... підрядок є рідним або переходить по масиву char, щоб створити нових символів.
ммм

16

Мені подобається цей метод (він виглядає трохи чистіше):

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

1
Гаразд, як уникнути рядка, щоб використовувати його як шаблон регулярного виразів?
rakslice

Не хочу, я просто використовую це для простого тексту
Оуен

15

Найпростіший шлях до цього, не використовуючи регулярного виразів, розбивається і приєднується як код тут:

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




13

Попередні відповіді занадто складні. Просто скористайтеся функцією заміни так:

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


10

Якщо ви намагаєтеся переконатися, що шукана рядок не буде існувати навіть після заміни, вам потрібно скористатися циклом.

Наприклад:

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, ','), але в якийсь момент регулярний вираз стає складним і досить повільним, щоб замість цього циклу].


10

Хоча люди згадували про використання регулярного вираження, але є кращий підхід, якщо ви хочете замінити текст незалежно від регістру тексту. Як і великі, або малі. Використовуйте нижче синтаксис

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

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

Ви можете ознайомитись з детальним прикладом тут .


з прикладу сайту: "/ toBeReplacedString / gi - це регулярний вираз, який потрібно використовувати. Тут g являє собою глобальну відповідність, і я являє собою нечутливі
регістри

8

Ви можете просто використовувати метод нижче

/**
 * 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

Просто додайте /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 означає глобальний

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.