Soru JavaScript'de bir dizenin tüm oluşumları nasıl değiştirilir?


Bu dizgim var:

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

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

sadece ilk ortaya çıkışını kaldırmak gibi görünüyor abc Yukarıdaki dizede. Nasıl değiştirebilirim herşey bunun oluşumu?


3173
2017-07-17 17:53


Menşei


stackoverflow.com/questions/1137436/... - Canavar
en basit: var str = 'abcabcbabc'; str.replace(/a/g, 'x'); --> 'xbcxbcxbc - FedericoCapaldo
Değiştirilecek dizginiz özel regex karakterleri içermediği sürece Federico'nın seçeneğinin mükemmel olduğunu unutmayın. - Andrew
@Andrew Özel regex karakterleri normal karakterlerden kaçabilir. - modiX
Merak eden herkes için, regex'ten ters eğik çizgi ile kaçabilirsiniz. Örneğin, str.replace (/ \] / g) çalışmalıdır, ancak str.replace (/] / g) değil, çünkü ']' özel bir regex karakteridir. - ashish-goel


Cevaplar:


Bütünlük adına, bunu yapmak için hangi yöntemi kullanmam gerektiğini düşünmeliyim. Bu sayfada diğer cevapların önerdiği gibi bunu yapmanın iki yolu vardır.

Not: Genel olarak, yerleşik prototiplerin JavaScript'te genişletilmesi genellikle önerilmez. String prototipinde sadece örnekleme amacıyla bir hipotetik standart yöntemin farklı uygulamalarını gösteren uzantılar olarak veriyorum. String yerleşik prototip.


Düzenli İfadeye Dayalı 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 sahnelerin arkasında nasıl düzenli ifadeler çalıştığı hakkında fazla bir şey bilmemekle birlikte, performans düşünmeden geçmişte bölüme yönelme ve uygulamaya katılma eğilimindeydim. Hangisinin daha verimli olduğunu merak ettiğimde ve hangi marjla, bunu öğrenmek için bir bahane olarak kullandım.

Chrome Windows 8 makinemde, düzenli ifade tabanlı uygulama en hızlı, ile bölünmüş ve uygulamaya% 53 daha yavaş katıl. Normal ifadelerin anlamı, kullandığım lorem ipsum girişi için iki kat daha hızlıdır.

Bunu kontrol et kıyaslama Bu iki uygulamayı birbiriyle karşılaştırmak.


Aşağıdaki yorumda @ThomasLeduc ve diğerleri tarafından belirtildiği gibi, normal ifadeye dayalı uygulama ile ilgili bir sorun olabilir. search olarak ayrılmış belirli karakterler içeriyor düzenli ifadelerde özel karakterler. Uygulama, arayanın dizeden önce çıkacağını ya da yalnızca karakterleri olmayan dizeleri yalnızca tabloya gireceğini varsayar. Düzenli ifadeler (MDN).

MDN ayrıca dizelerimizden kurtulmak için bir uygulama sağlar. Eğer bu standart olarak da standartlaştırılmış olsaydı RegExp.escape(str)ama alas, mevcut değil:

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

Arayabiliriz escapeRegExp bizim içinde String.prototype.replaceAll Bununla birlikte, uygulama, bunun performansı ne kadar etkileyeceğinden emin değilim (potansiyel olarak, tüm alfasayısal dizgiler gibi, kaçışın gerekmediği dizeler için bile).


1635
2017-07-12 01:46



Bir dizenin tüm geçitlerini değiştirirken g karakterinin ne olduğunu sorabilir miyim? - jonney
Android 4.1'de regexp yöntemi% 15 daha hızlıdır, ancak aranacak ifadeden kaçmıyorsunuz, bu nedenle bu karşılaştırma tamamlanmamıştır. - andreszs
Bu çözümle ilgili bir sorun var, eğer arama dizesi regexp ifadesinin özel karakterlerini içerdiği anlaşılıyorsa, bunlar yorumlanacaktır. @Sandy Unitedwolf cevabını tavsiye ederim. - Thomas Leduc
Birincisi bunu yapacak: 'bla.bla'.replaceAll ('. ',' _ '); "_______". İkincisi 'bla_bla' yapacak, daha genel olarak ne yapmak istiyorsun. - RobKohr
Cevabın üzerinde parlat. 5x daha fazla oy ile bir sonraki "yanlış" işaretli cevaba gidin. İstediğin bu. - HoldOffHunger


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

Yoruma cevaben:

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

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

Cevap olarak Tıkla'in yorumu, daha da basitleştirebilirsiniz:

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

Not: Düzenli ifadeler özel (meta) karakterler içerir ve bu nedenle, bir argümanı körü körüne geçmek tehlikelidir. find Önceden işlem yapmadan, bu karakterlerden kaçmak için fonksiyon. Bu kaplıdır Mozilla Geliştirici Ağı'ler Normal İfadeler Hakkında JavaScript RehberiAşağıdaki yardımcı program işlevini sunarlar:

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

Yani yapmak için replaceAll() daha güvenli fonksiyon, ayrıca içerirseniz aşağıdaki için değiştirilebilir escapeRegExp:

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

3597
2017-07-17 17:54



Düzenli ifadeler, bu "kutunun dışında" kendi "replaceAll" yönteminizi uygulamadan gerçekleştirmenin tek yoludur. Kullanımlarını sadece onları kullanmak için önermiyorum. - Sean Bright
Bu, bu yorumun kendi işlevim: function replaceAll(find, replace,str) { var re = new RegExp(find, 'g'); str = str.replace(re, replace); return str; } - Click Upvote
Büyük ihtarı replaceAll uygulama, eğer işe yaramazsa find meta karakterleri içerir. - Martin Ender
@SeanBright haklısın. Javascript'ini bir php kodunda kullandım, böylece kaçmak için ekstra bir ters eğik çizgi eklemeliydim. Kemanda kodun mükemmel. Kontrol etmeliydim. Özür jsfiddle.net/7y19xyq8 - Onimusha
@Bennett JavaScript yerel türlerinin prototipini genişletmek için kötü uygulama. - Emile Bergeron


Not: Bunu gerçek kodda kullanmayın.

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

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

Genel desen

str.split(search).join(replacement)

Bu, bazı durumlarda daha hızlı kullanıyordu replaceAll ve düzenli bir ifade, ancak modern tarayıcılarda artık böyle görünmüyor. Yani, bu sadece gerçek kodda değil, normal ifadeden kaçmaya ihtiyaç duymaktan kaçınmak için hızlı bir şekilde kullanılmalıdır.


1193
2017-07-17 20:29



Bu yöntemin daha fazla nesne ayırmasını, daha fazla çöp üretmesini ve dolayısıyla daha uzun süre beklemesini beklediğimden dolayı şaşırttı, ancak aslında bir tarayıcıda test ettiğimde bu yöntem tutarlı bir şekilde kabul edilen yanıttan% 20 daha hızlıydı. Sonuçlar elbette değişebilir. - MgSam
Kendimi merak ediyordum ve bunu kurdum: jsperf.com/replace-all-vs-split-join . Görünüşe göre, v8 diğer javascript motorlarına kıyasla dizileri ayırmak / birleştirmek için çok çılgın. - fabi
Çok güzel - ayrıca özel karakterleri geçerken sizi hatalı RegExps olasılığından kurtarır. Bir nesne özelliğindeki "bunu bul ve değiştir" için genel bir bayrak ekliyorum, ancak değiştirmem gerekirse endişelendim. veya "}" ve 3 ay sonra RegEx'i kullandığımı unuttum! - tobriand
Benim ipad2 / safari'mde, split / join, değiştirmekten% 65 daha yavaş olduğundan sonuçlarınız değişebilir. - mrk
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


İle düzenli bir ifade kullanarak g bayrak seti tüm yerini alacak:

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

Burada da görmek


507
2018-05-06 23:18



Kulağa aptalca bence, ama JS global regex birden fazla yerine geçmek için tek yol. - Mike
iyi teknik olarak geçebilirsin var sourceText örneklerin sayısını saymaknumOfInstances) kullanarak substring ya da bölün ve uzunluğu (diğer stratejiler arasında) sayın. thatWhichYouWantToReplace o zaman yap for (var i = 0; i < numOfInstances; i++){ sourceText = sourceText.replace('thatWhichYouWantToReplace', ''); } veya daha kolay bir süre döngü kullanın (while sourceText.indexOf(thatWhichYouWantToReplace > -1){ sourceText = sourceText.replace(...)) ama neden kullandığınızı bu şekilde yapmak istediğinizi anlamıyorum /g çok kolay ve muhtemelen daha performanslıdır. - Zargold


İşte kabul edilen cevaba dayanan bir dizi 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 ve onlardan kaçmanız 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/


90
2018-02-11 23:03



Ama ya eğer find gibi karakterler içerir . veya $ normal ifadede özel anlamları var mı? - callum
@callum Bu durumda, bulma değişkeninizden kaçmak zorunda kalacaksınız (yukarıdaki düzenlemeye bakınız). - jesal
Sahip olmadığınız nesneleri değiştirmeyin - Aamir Afridi
jesal, bu karşılaştığım bir dize değiştirme sorunu için harika bir çözüm ve görünüşte JavaScript dizeleri "değişmezlik" üstesinden gelir. Siz veya başkası bu prototip işlevinin dizelerin değişmezliğini nasıl geçersiz kıldığını açıklayabilir misiniz? Bu yapar iş; Sadece bu yardımcı soruyu anlamak istiyorum. - Tom
@ Tom: Bu değil değişmezliğin üstesinden gelmek: var str = this değişmez dizgeye ikinci bir referans oluşturur. replace yöntem uygulanır, bu da bir yeni değişmez dize. Bu prototip işlevleri yeni bir değişmez dizge döndürür, eğer yapamazsanız, yazabilirsiniz. someStrVar.replaceAll('o', '0'); ve someStrVar değiştirilecek. Bunun yerine, yazmak zorundasın someStrVar = someStrVar.replaceAll('o', '0'); <- tutmak için var olan değeri atayın. yeni değişmez dize. Bunun etrafında bir yolu yok. Konsolda dene: x = 'foobar'; x.replaceAll('o', '0'); x; - Elias Van Ootegem


Güncelleştirme:

Bir güncelleme için biraz geç oldu, ama bu soruya yeni geldiğimden ve önceki cevabımın mutlu olduğum bir şey olmadığını fark ettim. Tek bir kelimeyi değiştirmeyi içeren soru söz konusu olduğundan, hiç kimse kelime sınırlarını kullanmayı düşünmez.\b)

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

Bu, çoğu durumda kelimelerin bir kısmını değiştirmeyi önleyen basit bir ifadedir. Ancak, bir çizgi - hala bir kelime sınırı olarak kabul edilir. Bu nedenle koşulların bu gibi dizeleri değiştirmekten kaçınmak için 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 şu soruyla aynı: Javascript, "" "ile" "" değiştirin

@Mike, orada verdiğim cevabı kontrol et ... regexp, bir altrtmanın çoklu oluşumlarını değiştirmenin tek yolu değil. Esnek düşün, bölünmüş düşün!

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

Alternatif olarak, kelime parçalarının değiştirilmesini önlemek için - onaylanmış cevap da yapılacaktır! Bu konuyu normal kabullerle ifade edebilirim, itiraf ediyorum, biraz daha karmaşık ve bunun bir sonucu olarak, biraz daha yavaş:

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

Çıktı, bu dizede / cat / g ifadesini kullanarak kabul edilen yanıtla aynıdı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" ?? 

Oops gerçekten, bu muhtemelen istediğin şey değil. O zaman nedir? IMHO, sadece 'kedi' yerine koşullu bir regex. (örneğin, 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şılar. Elbette, tam anlamıyla değil, ama başlaman için yeterli olmalı. Bu sayfalarda biraz daha okumayı öneriyorum. Bu, özel ifadelerinizi 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 ek:

Bu sorunun hala çok fazla göründüğü göz önüne alındığında, bir örnek ekleyebileceğimi düşündüm. .replace geri arama işlevi ile kullanılır. Bu durumda, ifadeyi önemli ölçüde basitleştirir ve Doğru büyük harf kullanımıyla değiştirmek veya her ikisini de değiştirmek gibi daha fazla esneklik sağlar. cat ve cats tek seferde:

'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

75
2018-03-01 10:02



Bence ek ilginç kısım alt tarafa yerleştirilmelidir. ps .: Sadece ilk hattın yarısının alandan çıktığını fark ettim, bunu düzeltmeme izin vereyim!


Genel bir normal ifadeyle karşılaştır:

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

45
2018-05-06 23:23





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

Veya replaceAll işlevini buradan deneyin:

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

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

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

DÜZENLE: Değiştirme durumu hakkında açıklama

'ReplaceAll' yöntemi, String'in prototipine eklendi. Bu, tüm string nesneleri / literals için mevcut 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'

35
2017-07-17 17:55



Prototype kullanmayanlar için replaceAll () işlevini yeniden yazabilir misiniz? - Click Upvote
@Click Upvote .... prototip kullanıyorsunuz, tüm JS nesnelerinin bir parçası. Ben JS kitaplığı prototype.js düşünüyorum düşünüyorum. - seth
Seth, küçük bir düzeltme. Bir prototipe yöntem eklerseniz, bu türdeki tüm nesneler kullanılabilir. ReplceAll yöntemi String prototype'e eklenmiştir ve tüm dize nesneleri için çalışmalıdır. - SolutionYogi
@solutionyogi - Evet, daha önce prototip (doğru) kullandım. Sadece OP'nin prototype.js'yi kastettiğimi varsaydığım "prototip kullanmama" hakkındaki yorumunu ele alıyordum (belki de yanlış mı?). JavaScript nesnelerinin bir prototipi olduğunu söylemeye çalıştığım gibi "bir prototip" demeliydim. Böylece OP zaten “dolaylı” bir şekilde de olsa “prototip kullanıyordu”. Dolaylı, burada kullanmak için yanlış bir terim olabilir ama yorgunum, bu yüzden culpa. - seth


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

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


29
2017-09-10 14:59



Basit, kolay ve muhtemelen en performanslı seçenek: güzel cevap. - machineghost
Performans açısından bilmiyorum, ama .... işe yarıyor. - Emilio Grisolía
Aslında, kişisel olarak metrik yapmamışken, bölme / katılma genellikle çok verimli bir çözümdür. - machineghost
kromda bile,% 100 daha hızlı firefox ve% 50 daha yavaş IE'de ...: jsperf.com/replace-regex-split-join - Olivier


Normal bir ifade kullanın:

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

27
2017-07-17 17:56