Bir dizenin tüm oluşumları nasıl değiştirilir?


4379

Bu dize var:

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

Yapma:

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

abcyukarıdaki dizede yalnızca ilk oluşumunu kaldırmış gibi görünüyor .

Tüm oluşumlarını nasıl değiştirebilirim ?


5
Tüm tekrarlarını değiştirirken abade abababirlikte cabeklediğiniz yapmak sonuçlanır? caba? abca? cca?
reinierpost

String.prototype.replaceAll()Safari 13.1'de gönderildi ve şimdi Firefox Nightly ve Chrome Dev ve Canary'de ve Firefox 77 ve Chrome 85'te gönderilecek. Henüz MDN'de belgelenmedi, ancak github.com/tc39/proposal-string-replaceall#high-level-api açıklayıcıya sahiptir: “ searchValue bir dize ise, searchValue'nun tüm tekrarlamalarının String.prototype.replaceAllyerine geçer (sanki veya genel ve düzgün bir şekilde kaçan normal ifade kullanılmış gibi). Eğer searchValue olmayan bir küresel düzenli ifadedir, bir istisna”atar.split(searchValue).join(replaceValue)String.prototype.replaceAll
sideshowbarker

Yanıtlar:


1609

Not: Bunu kritik performans kodunda kullanmayın.

Basit bir değişmez değer dizesi için normal ifadelere alternatif olarak,

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

Genel kalıp

str.split(search).join(replacement)

Bu, bazı durumlarda kullanmaktan daha hızlıydı replaceAll ve düzenli bir ifadeden , ancak modern tarayıcılarda artık böyle görünmüyor.

Deney: https://jsperf.com/replace-all-vs-split-join

Sonuç: Performans açısından kritik bir kullanım durumunuz varsa (örneğin yüzlerce dizeyi işlemek gibi), Regexp yöntemini kullanın. Ancak çoğu tipik kullanım durumunda, bu özel karakterler hakkında endişelenmenize gerek yoktur.


147
Bu yöntemin daha fazla nesne tahsis etmesini, daha fazla çöp oluşturmasını ve dolayısıyla daha uzun sürmesini beklediğim için beni şaşırttı, ancak aslında bir tarayıcıda test ettiğimde bu yöntem sürekli olarak kabul edilen yanıttan yaklaşık% 20 daha hızlıydı. Sonuçlar elbette değişebilir.
MgSam

42
Kendimi merak ettim ve bunu ayarladım: jsperf.com/replace-all-vs-split-join . Görünüşe göre v8 diğer javascript motorlarına kıyasla bölme / birleştirme dizilerinde çılgınca hızlı.
fabi

8
Çok hoş - özel karakterleri iletirken sizi kötü RegExps olasılığından da kurtarır. Bir nesne özelliğinde "bu bulmak ve değiştirmek" için genel bir bayrak ekliyorum, ama "" yerine gerekiyorsa endişeliydi. veya "}" ve 3 ay sonra RegEx'i kullandığımı unuttum!
tobriand

9
Ve String.prototype olarak: String.prototype.replaceAll = function(f,r){return this.split(f).join(r);}. Kullanımı: "My string".replaceAll('st', '');"Benim yüzüğüm" üretir
MacroMan

8
Bu uyarının üretimde kullanılmaması için bir neden göremiyorum. Bu, birden fazla tekrarlamayı değiştirmek istediğiniz için normal bir ifadeden kaçmaktan ziyade bir hack değildir, ancak ilk etapta bir normal ifadeye ihtiyaç duymazsınız. Sadece bu "hack" denilen replaceAllşeyi güzel bir fonksiyona sarın ve her şey kadar okunabilir hale gelir. Performans kötü olmadığından, bu çözümden kaçınmak için hiçbir neden yoktur.
Youen

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

Yoruma yanıt olarak:

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

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

Click Upvote'un yorumuna yanıt olarak , daha da basitleştirebilirsiniz:

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

Not: Normal ifadeler özel (meta) karakterler içerir ve bu nedenle findyukarıdaki işlevde bir argümanı bu karakterlerden kaçmak için ön işleme koymadan körü körüne geçirmek tehlikelidir . Bu kaplıdır Mozilla Geliştirici Ağı 'nın Normal İfadeler JavaScript Kılavuz aşağıdaki fayda fonksiyonu sunmak (en azından iki kez bu yanıt yazılmaya başlandı yana değişti ki, bu yüzden potansiyel güncellemeler için MDN siteyi kontrol emin olun):

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

Bu nedenle, replaceAll()yukarıdaki işlevi daha güvenli hale getirmek için, aşağıdakileri de eklerseniz aşağıdakilere değiştirilebilir escapeRegExp:

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

4
Düzenli ifadeler, kendi "replaceAll" yönteminizi uygulamadan bu "kutudan çıkar" işlemini gerçekleştirmenin tek yoludur. Sadece onları kullanmak uğruna kullanılmalarını önermiyorum.
Sean Bright

10
Bu benim yorumdan kendi fonksiyonum: function replaceAll(find, replace,str) { var re = new RegExp(find, 'g'); str = str.replace(re, replace); return str; }
Upvote

47
Uygulamanın ana uyarısı , metakarakterler içeriyorsa replaceAllçalışmayacaktır find.
Martin Ender

1
@SeanBright haklısın. Ben kaçmak için ekstra bir ters eğik çizgi eklemek zorunda böylece bir php kodunda javascript kullanılır. Kemanda kodunuz mükemmel. Kontrol etmeliydim. Özür jsfiddle.net/7y19xyq8
Onimusha


2437

Tamlık uğruna, bunu yapmak için hangi yöntemi kullanmam gerektiğini düşündüm. Bunu, bu sayfadaki diğer yanıtlar tarafından önerildiği gibi yapmanın temel olarak iki yolu vardır.

Not: Genel olarak, yerleşik prototiplerin JavaScript'te genişletilmesi genellikle önerilmez. Yerleşik prototip üzerinde varsayımsal bir standart yöntemin farklı uygulamalarını gösteren, örnekleme amacıyla String prototipi üzerinde uzantılar sağlıyorum String.


İfade Tabanlı Düzenli Uygulama

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

Böl ve Katıl (İşlevsel) Uygulaması

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

Verimlilik açısından düzenli ifadelerin perde arkasında nasıl çalıştığını çok fazla bilmeden, performansı düşünmeden geçmişte bölünmeye ve uygulamaya katılmaya eğilimliydim. Hangisinin daha verimli olduğunu ve ne kadar marjla olduğunu merak ettiğimde, bunu bulmak için bir bahane olarak kullandım.

Chrome Windows 8 makinemde , normal ifade tabanlı uygulama en hızlı , split ve join uygulaması% 53 daha yavaş . Yani normal ifadeler, kullandığım lorem ipsum girişi için iki kat daha hızlıdır.

Birbirine karşı bu iki uygulamayı çalıştıran bu kıstasa göz atın .


@ThomasLeduc ve diğerleri tarafından aşağıdaki yorumda belirtildiği searchgibi , normal ifadelerde özel karakterler olarak ayrılmış belirli karakterler içeriyorsa , düzenli ifade tabanlı uygulamada bir sorun olabilir . Uygulama, arayanın dizeden önceden kaçacağını veya yalnızca Normal İfadeler (MDN) tablosundaki karakterleri olmayan dizeleri geçireceğini varsayar .

MDN ayrıca tellerimizden kaçmak için bir uygulama sağlar. Bunun da standartlaştırılması güzel olurdu RegExp.escape(str), ama ne yazık ki, mevcut değil:

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

Uygulamamız escapeRegExpiçinde arayabiliriz String.prototype.replaceAll, ancak bunun performansı ne kadar etkileyeceğinden emin değilim (potansiyel olarak tüm alfanümerik dizeler gibi kaçışın gerekli olmadığı dizeler için bile).


8
Android 4.1'de regexp yöntemi% 15 daha hızlıdır, ancak aramak için ifadeden kaçmazsınız, bu nedenle bu karşılaştırma ölçütü eksiktir.
andreszs

33
Bu çözümle ilgili bir sorun var, arama dizeniz normal ifade ifadesinin özel karakterlerini içeriyorsa, bunlar yorumlanacaktır. @Sandy Unitedwolf cevabını tavsiye ederim.
Thomas Leduc

2
İlki bunu yapacaktır: 'bla.bla'.replaceAll ('. ',' _ '); "_______". İkincisi, daha genel olarak yapmak istediğiniz şey olan 'bla_bla' yapacak.
RobKohr

1
@ThomasLeduc, bahsettiğiniz sorunun lodash => lodash.com/docs/4.17.5#escapeRegExp
Matthew Beck

1
Bunu, yerel nesneyi genişletmenin neden kötü bir fikir olduğunu merak eden gelecekteki izleyiciler için burada bırakmak: stackoverflow.com/questions/14034180/…
Ben Cooper

692

gBayrak kümesiyle normal bir ifade kullanmak , bunların yerini alacaktır:

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

Ayrıca bkz.


15
Biraz aptalca düşünüyorum, ama JS küresel regex birden fazla yerine koymanın tek yoludur.
Mike

5
iyi teknik olarak döngü var sourceTextsayısı ( numOfInstances) kullanarak substringveya bölün ve sonra (diğer stratejiler arasında) uzunluğunu saymak döngü thatWhichYouWantToReplaceyapabilirsiniz for (var i = 0; i < numOfInstances; i++){ sourceText = sourceText.replace('thatWhichYouWantToReplace', '');daha da kolay sadece bir while döngü ( while sourceText.indexOf(thatWhichYouWantToReplace > -1){ sourceText = sourceText.replace(...)) kullanın ama neden istemediğinizi görmüyorum kullanırken bu şekilde yapmak /gçok kolay ve muhtemelen daha performanslı.
Mart'ta Zargold

@Zargold Değiştirmeden sonra bile tüm örnekleri değiştirdiğinizden emin olmak için bir döngü yapmak istersiniz, bu oldukça yaygın bir gotcha'dır. Aşağıdaki cevabımı aşağıda görebilirsiniz stackoverflow.com/a/26089052/87520
SamGoody

109

Kabul edilen cevaba dayanan bir dize prototip işlevi:

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

DÜZENLE

Eğer senin findözel karakterler içerecek sonra onları kaçmak gerekir:

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

Keman: http://jsfiddle.net/cdbzL/


5
Peki ya normal ifade findgibi .veya $özel anlamları olan karakterler içeriyorsa ?
kallum

1
@callum Bu durumda bulma değişkeninizden kaçmanız gerekir (yukarıdaki düzenlemeye bakın).
jesal


jesal, bu karşılaştığım bir dize değiştirme sorunu için harika bir çözüm ve görünüşe göre JavaScript dizelerin "değişmezlik" üstesinden gelir. Siz veya bir başkası bu prototip işlevinin dizelerin değişmezliğini nasıl geçersiz kıldığını açıklayabilir mi? Bu does işi; Sadece ortaya koyduğu bu yan soruyu anlamak istiyorum.
Tom

1
@Tom: Değişmezliğin üstesinden gelmez : yöntemin uygulandığı var str = thisdeğişmez dizeye ikinci bir başvuru oluşturur replace, bu da yeni bir değişmez dizge döndürür . bu prototip işlevleri yeni bir değiştirilemez dize döndürür, değilse, yazabilirsiniz someStrVar.replaceAll('o', '0');ve someStrVardeğiştirilebilir. Bunun yerine, someStrVar = someStrVar.replaceAll('o', '0');var değişkenini yeni değişmez dizgiyi tutacak şekilde ayarlamak için <- yeniden atamanız gerekir . bunun hiçbir yolu yok. Konsolda deneyin:x = 'foobar'; x.replaceAll('o', '0'); x;
Elias Van Ootegem

87

Güncelleme:

Bir güncelleme için biraz geç, ama bu soruyu tökezlediğimden ve önceki cevabımın mutlu olduğum bir cevap olmadığını fark ettim. Sorusu tek kelime replaceing dahil beri 's inanılmaz kimse (kelime sınırlarını kullanarak düşünce \b)

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

Bu, çoğu durumda kelimelerin parçalarını değiştirmekten kaçınan basit bir regex'tir. Ancak, kısa çizgi -hala bir kelime sınırı olarak kabul edilir. Bu nedenle, aşağıdaki gibi dizeleri değiştirmekten kaçınmak için bu durumda koşullu kullanılabilir 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"

temel olarak, bu soru buradaki soru ile aynıdır: Javascript "" "yerine" '' "

@Mike, orada verdiğim yanıtı kontrol edin ... regexp, bir sübvansiyonun birden fazla tekrarını değiştirmenin tek yolu değildir. Esnek düşünün, bölünmüş düşünün!

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

Alternatif olarak, kelime bölümlerinin değiştirilmesini önlemek için - onaylanan cevap da yapılacaktır! İtiraf ediyorum, biraz daha karmaşık ve bunun bir sonucu olarak, biraz daha yavaş olan düzenli ifadeleri kullanarak bu sorunu çözebilirsiniz:

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

Çıktı, kabul edilen yanıtla aynıdır, ancak bu dizede / cat / g ifadesi kullanılır:

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

Üzgünüz, bu muhtemelen istediğiniz şey değil. Öyleyse nedir? IMHO, sadece şartlı olarak 'kedinin' yerini alan bir regex. (yani bir kelimenin parçası değil), şöyle:

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"

Tahminimce bu ihtiyaçlarınızı karşılıyor. Tabii ki tam geçirmez değil, ama başlamanız için yeterli olmalı. Bu sayfalarda biraz daha okumanızı tavsiye ederim. Bu, özel ihtiyaçlarınızı karşılamak için bu ifadeyi mükemmelleştirmede yararlı olacaktır.

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

http://www.regular-expressions.info


Son ekleme:

Bu sorunun hala çok fazla görüş aldığı göz önüne alındığında, .replacegeri arama işleviyle kullanılan bir örnek ekleyebileceğimi düşündüm . Bu durumda, bu dramatik ifadeyi kolaylaştırır ve doğru büyük harf ile değiştirerek ya da her ikisi yerine gibi, daha fazla esneklik sunar catve catsbir go in:

'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

Ek ilginç bölümün alt kısmına yerleştirilmesi gerektiğini düşünüyorum. ps .: İlk satırın yarısının alanın dışında olduğunu fark ettim, bunu düzeltmeme izin ver!

69

Genel bir düzenli ifadeyle eşleşme:

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

60

Tek seferlik kullanım için:

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

Birden çok kez değiştirmek için şunları kullanın:

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

Birisi değiştirmeniz gerekiyor \ n, bunu gibi yapabilirsiniz:replace(/\n/g, '<br/>')
Phan Van Linh

58

Bunlar en yaygın ve okunabilir yöntemlerdir.

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

Yöntem 1:

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

Yöntem 2:

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

Yöntem 3:

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

Yöntem 4:

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

Çıktı:

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

Veya buradan replaceAll işlevini deneyin:

Yerleşik nesneleri genişleten kullanışlı JavaScript yöntemleri nelerdir?

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

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

EDIT: Değiştirme hakkında açıklama

'ReplaceAll' yöntemi String'in prototipine eklenir. Bu, tüm dize nesneleri / değişmez değerleri için kullanılabilir olacağı anlamına gelir.

Örneğin

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

2
Prototip kullanmayanlar için replaceAll () işlevini yeniden yazabilir misiniz?
Click Olumlu oy

@Click Upvote .... prototip kullanıyorsunuz, bu tüm JS nesnelerinin bir parçası. Bence prototype.js JS kütüphanesini düşünüyorsunuz.
seth

seth, küçük bir düzeltme. Bir prototipe yöntem eklerseniz, bu türdeki tüm nesneler tarafından kullanılabilir. ReplceAll yöntemi, String prototipine eklendi ve tüm dize nesneleri için çalışmalıdır.
SolutionYogi

@solutionyogi - Evet, daha önce prototip (doğru) kullandım. Ben sadece OP prototype.js (belki de yanlış?) Anlamına geldiğini varsayıyorum "prototip kullanma değil" hakkında yorum ele oldu. JavaScript nesnelerinin bir prototipi olduğunu söylemeye çalıştığım için "bir prototip" demeliydim. Böylece OP, "dolaylı" bir şekilde de olsa zaten "prototip kullanıyordu". Dolaylı burada kullanmak için yanlış terim olabilir ama çok yorgunum.
seth

41

Kullanılması RegExphalinde JavaScript unutma, sadece basit kodunun altına böyle bir şey yapmak, sizin için iş yapabilirdi /giçin hangi çarpıcı sonra küresel :

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

Yeniden kullanmayı düşünüyorsanız, bunu sizin için yapmak için bir işlev oluşturun, ancak yalnızca bir satır işlevi olduğu için önerilmez, ancak yine bunu yoğun bir şekilde kullanırsanız, böyle bir şey yazabilirsiniz:

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

ve kodunuzda aşağıdaki gibi tekrar tekrar kullanın:

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

Ancak daha önce de belirttiğim gibi, yazılacak satırlar veya performans açısından büyük bir fark yaratmayacak, sadece işlevi önbelleğe almak uzun dizelerde daha hızlı bir performans ve yeniden kullanmak istiyorsanız iyi bir DRY kodu uygulaması etkileyebilir.


40

Tüm 'abc'yi' x 'ile değiştirmek istediğinizi varsayalım:

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

Dize prototipini değiştirmekten daha basit bir şey düşünmeye çalışıyordum.


1
Basit, kolay ve muhtemelen en performanslı seçenek: güzel cevap.
machineghost

Aslında, kişisel olarak metriklememiş olsam da, bölme / birleştirme genellikle çok performanslı bir çözümdür.
machineghost



32

Tek tırnak işaretleri:

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

    return text;
}

2
Dizeleri değiştirmek için ikinci satırı nasıl değiştirebilirim? Bu işe yaramaz: text = text.replace ('hey', 'merhaba'); Herhangi bir fikir?
Stefan Đorđević

2
Tabii Stefan, işte kod ... text = text.replace (/ hey / g, 'merhaba');
Chris Rosete

26

// sayı oluşumları 0 oluncaya kadar döngüye sokun. VEYA basitçe kopyalayın / yapıştırın

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

23
Bu yöntem tehlikelidir, kullanmayın. Yeni dize arama anahtar sözcüğünü içeriyorsa, sonsuz bir döngü oluşur. En azından, .indexOfbir değişkenin sonucunu saklayın ve bu değişkeni ikinci parametresi olarak kullanın .indexOf(anahtar kelime eksi uzunluğu, değiştirme dizesinin uzunluğu).
Rob W

İlk olarak arama desenini bir girişli unicode char ile değiştirmeyi düşünüyorum, bu giriş dizisinde kullanılmadığından eminiz. Like U + E000 Özel alandaki gibi. Ve sonra tekrar hedefe yerleştirin. Bunu burada inşa ettim.. İyi bir fikir olup olmadığından emin değilim.
Lux

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

benim için yukarıdaki cevaplardan daha iyi çalıştı. yaninew RegExp("abc", 'g')'g' metnin ( "abc") tüm oluşumuyla ( bayrağı) eşleşen bir RegExp oluşturur . İkinci bölüm ise boş dize ( "") ile değiştirilir. strdizedir ve replace(...)sonucu döndürdüğümüz gibi geçersiz kılmamız gerekir , ancak geçersiz kılmamamız gerekir. Bazı durumlarda bunu kullanmak isteyebilirsiniz.


Bu kod snippet'i çözüm olsa da, bir açıklama da dahil olmak üzere mesajınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın.
yivi

Evet, haklısın. katma. Ayrıca orijinal soruya cevap için düzenledi :)
csomakk

Not:
regex'deki

25

Bu, normal ifadeler kullanmayan en hızlı sürümdür .

Revize jsperf

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

Böl ve birleştir yönteminin neredeyse iki katıdır .

Buradaki bir yorumda belirtildiği gibi, omitdeğişkeniniz aşağıdaki gibi içeriyorsa bu çalışmaz place: replaceAll("string", "s", "ss")çünkü her zaman kelimenin başka bir örneğini değiştirebilecektir.

Yinelemeli değiştirmemde daha da hızlı değişen başka bir jsperf var ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • 27 Temmuz 2017 Güncellemesi: Görünüşe göre RegExp, yakın zamanda yayınlanan Chrome 59'da en hızlı performansa sahip.

Çözümünü sevdim ... Keşke sana +10 verebilsem ama işte + 1'im. Sonsuz döngü sorunu önlemek için daha düşük bir dizinde bir eşleşme bulunursa değiştirilen alt dizenin dizin depolamak ve sonraki atlamak düşünüyorum. Performans hakkında yorum yapamam çünkü test etmedim ama bu mükemmellikte sadece 2 sentim.
Fr0zenFyr

@ fr0zenfyr Eğer ihmalin yerinde olup olmadığını kontrol etmek istiyorsanız (sonsuz döngüyü önlemek için) Eşleşme if(place.replace(omit) === omit) {yok gibi bir koşullu yapabilirsiniz , bu yüzden döngü değiştirmeyi kullanmak güvenlidir, bu } else {yüzden böl ve katıl gibi farklı bir yöntem kullanın}
Cole Lawrence

Hmm .. ama iki çözümü birleştirmenin ne anlamı var? Ben zaten zaten bir split / katılmak yaklaşım hayranı değilim .. tavsiye için teşekkürler ..
Fr0zenFyr

@ Fr0zenFyr İki çözümü birleştirmenin amacının, daha hızlı olanı kullanamazsanız (döngü sonsuz olduğunda) daha yavaş bir yönteme geri dönmek olduğuna inanıyorum. Bu nedenle, işlevselliği verimli bir şekilde sağlamak, ancak arıza olasılığı olmadan güvenli bir koruma olacaktır.
Cole Lawrence

@momomo nasıl kusurlu?
SandRock

24

Verim

Bugün 27.12.2019 Seçilen çözümler için macOS v10.13.6 (High Sierra) üzerinde testler yapıyorum .

Sonuçlar

  • str.replace(/abc/g, '');( C ) Tüm dizeleri için iyi bir çapraz tarayıcı hızlı bir çözümdür.
  • split-join( A, B ) veya replace( C, D ) tabanlı çözümler hızlıdır
  • while( E, F, G, H ) tabanlı çözümler yavaştır - küçük teller için genellikle ~ 4 kat daha yavaş ve uzun teller için yaklaşık ~ 3000 kez (!) Daha yavaş
  • Yineleme çözümleri ( RA, RB ) yavaştır ve uzun dizeler için çalışmaz

Ayrıca kendi çözümümü de yaratıyorum. Şu anda soru işini yapan en kısa olanı gibi görünüyor:

str.split`abc`.join``

ayrıntılar

Testler Chrome 79.0, Safari 13.0.4 ve Firefox 71.0 (64 bit) üzerinde gerçekleştirildi. Testler RAve RBkullanım özyineleme. Sonuçlar

Resim açıklamasını buraya girin

Kısa dize - 55 karakter

BURADA makinenizde testler yapabilirsiniz . Chrome sonuçları:

Resim açıklamasını buraya girin

Uzun karakter dizisi: 275000 karakter

Özyinelemeli çözümler RA ve RB verir

RangeError: Maksimum çağrı yığını boyutu aşıldı

1 milyon karakter için Chrome'u bile kırıyorlar

resim açıklamasını buraya girin

Diğer çözümler için 1M karakterleri için testler yapmaya çalışıyorum, ancak E, F, G, H o kadar çok zaman alıyor ki tarayıcı betiği kırmamı istiyor, bu yüzden test dizesini 275K karaktere küçültüyorum. BURADA makinenizde testler yapabilirsiniz . Chrome için sonuçlar

resim açıklamasını buraya girin

Testlerde kullanılan kod


1
Şimdi bu derinlemesine bir cevap! Çok teşekkür ederim! Rağmen, merak ediyorum "yeni RegExp (...)" sözdizimi neden bu kadar bir gelişme sağlar.
Márk Gergely Dolinka

21

Bulmak istediğiniz şey bir dizede zaten varsa ve kullanışlı bir normal ifade escaper'unuz yoksa join / split'i kullanabilirsiniz:

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

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


Teşekkürler! Bu çözüm sorunum için mükemmel çalışıyor :)
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;
}

Acaba ne kadar iyi performans gösterir ... alt dize yerli ya da yeni karakterler oluşturmak için char dizisi üzerinde yürüyor.
mmm

16

Bu yöntemi seviyorum (biraz daha temiz görünüyor):

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

1
Tamam, normal ifade deseni olarak kullanmak için dizeden nasıl kaçıyorsunuz?
rakslice

Yapmıyorum, sadece düz metin için kullanıyorum
Owen

15

Herhangi bir regex kullanmadan bunun en basit yolu bölünmüş ve buradaki kod gibi katılın:

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


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

13

Dize benzer bir desen içeriyorsa abccc, bunu kullanabilirsiniz:

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

13

Önceki cevaplar çok karmaşık. Sadece replace işlevini şu şekilde kullanın:

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

Misal:

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

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

console.log(res);


10

Aradığınız dizenin, değiştirmeden sonra bile var olmamasını sağlamaya çalışıyorsanız, bir döngü kullanmanız gerekir.

Örneğin:

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

Tamamlandığında, hala 'test abc' olacak!

Bunu çözmek için en basit döngü:

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

Ancak bu, her döngü için iki kez değiştirmeyi çalıştırır. Belki biraz daha verimli ancak daha az okunabilir bir form için birleştirilebilen (oy kullanma riski):

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

Bu özellikle yinelenen dizeler ararken faydalı olabilir.
Örneğin, 'a ,,, b' varsa ve yinelenen virgüllerin tümünü kaldırmak istiyoruz.
[Bu durumda, .replace (/, + / g, ',') yapılabilir, ancak bir noktada normal ifade karmaşık ve döngü için yeterince yavaş hale gelir.]


10

Her ne kadar insanlar normal ifadenin kullanımından bahsetse de, metnin durumuna bakılmaksızın metni değiştirmek istiyorsanız daha iyi bir yaklaşım vardır. Büyük veya küçük harf gibi. Aşağıdaki sözdizimini kullan

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

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

Ayrıntılı örneğe buradan bakabilirsiniz .


Örnek siteden: "/ toBeReplacedString / gi kullanmanız gereken normal ifadedir. Burada g global eşleşmeyi temsil eder ve i büyük / küçük harfe duyarlı değildir. Varsayılan olarak normal ifadeler büyük / küçük harfe duyarlıdır"
alikuli

8

Sadece aşağıdaki yöntemi kullanabilirsiniz

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

Sadece ekle /g

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

için

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

/g küresel demek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.