Bagaimana cara mengganti semua kemunculan string?

4383

Saya punya string ini:

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

Perbuatan:

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

tampaknya hanya menghilangkan kemunculan pertama abcdalam string di atas.

Bagaimana saya bisa mengganti semua kemunculannya?

Klik Upvote
sumber
5
Saat mengganti semua kejadian dari abadalam ababadengan ca, yang mengakibatkan yang Anda harapkan? caba? abca? cca?
reinierpost
String.prototype.replaceAll()dikirim di Safari 13.1 dan sekarang di Firefox Nightly dan Chrome Dev dan Canary dan akan dikirim di Firefox 77 dan Chrome 85. Ini belum didokumentasikan dalam MDN, tetapi github.com/tc39/proposal-string-replaceall#high-level-api memiliki explainer: “Jika searchValue adalah string, String.prototype.replaceAllganti semua kemunculan searchValue (seolah-olah .split(searchValue).join(replaceValue)atau ekspresi reguler global & yang diloloskan dengan benar telah digunakan). Jika searchValue adalah ekspresi reguler non-global, berikanString.prototype.replaceAll pengecualian ”
sontonbarker

Jawaban:

1612

Catatan: Jangan gunakan ini dalam kode kritis kinerja.

Sebagai alternatif ekspresi reguler untuk string literal sederhana, Anda bisa menggunakannya

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

Pola umumnya adalah

str.split(search).join(replacement)

Ini digunakan dalam beberapa kasus lebih cepat daripada menggunakan replaceAlldan ekspresi reguler, tapi itu tampaknya tidak menjadi kasus lagi di browser modern.

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

Kesimpulan: Jika Anda memiliki kasus penggunaan kritis kinerja (misalnya memproses ratusan string), gunakan metode Regexp. Tetapi untuk sebagian besar kasus penggunaan umum, ini layak tidak perlu khawatir tentang karakter khusus.

Matthew Crumley
sumber
147
Itu mengejutkan saya, karena saya berharap metode ini akan mengalokasikan lebih banyak objek, membuat lebih banyak sampah, dan dengan demikian memakan waktu lebih lama, tetapi ketika saya benar-benar menguji di browser metode ini secara konsisten sekitar 20% lebih cepat daripada respons yang diterima. Hasil dapat bervariasi, tentu saja.
MgSam
42
Saya ingin tahu sendiri, dan mengatur ini: jsperf.com/replace-all-vs-split-join . Tampaknya v8 hanya gila cepat di pemisahan / bergabung array dibandingkan dengan mesin javascript lainnya.
fabi
8
Sangat bagus - juga menyelamatkan Anda dari kemungkinan RegExps yang buruk ketika mengirimkan karakter khusus. Saya menambahkan bendera generik untuk "menemukan ini dan menggantinya" di properti objek, tetapi khawatir jika saya perlu mengganti "." atau "}" dan lupa saya menggunakan RegEx 3 bulan kemudian!
tobriand
9
Dan sebagai String.prototype: String.prototype.replaceAll = function(f,r){return this.split(f).join(r);}. Penggunaan: "My string".replaceAll('st', '');menghasilkan "Cincin saya"
MacroMan
8
Saya tidak melihat alasan peringatan untuk tidak menggunakan ini dalam produksi. Ini tidak lebih sebagai retasan daripada keluar dari regex hanya karena Anda ingin mengganti banyak kejadian, tetapi tidak perlu regex sejak awal. Hanya membungkus ini yang disebut "hack" dalam replaceAllfungsi yang bagus , dan itu menjadi sama terbaca dengan hal lain. Karena kinerja tidak buruk, tidak ada alasan untuk menghindari solusi ini.
youen
4385
str = str.replace(/abc/g, '');

Menanggapi komentar:

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

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

Sebagai tanggapan terhadap komentar Klik Suara , Anda dapat lebih menyederhanakannya:

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

Catatan: Ekspresi reguler mengandung karakter khusus (meta), dan karena itu berbahaya untuk secara membabi buta menyampaikan argumen dalam findfungsi di atas tanpa pra-pemrosesan untuk menghindari karakter tersebut. Hal ini tercakup dalam Mozilla Developer Jaringan 's JavaScript Panduan pada Regular Expressions , di mana mereka menyajikan fungsi utilitas berikut (yang telah berubah setidaknya dua kali sejak jawaban ini awalnya ditulis, jadi pastikan untuk memeriksa situs MDN untuk update potensial):

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

Jadi untuk membuat replaceAll()fungsi di atas lebih aman, itu dapat dimodifikasi menjadi yang berikut jika Anda juga menyertakan escapeRegExp:

function replaceAll(str, find, replace) {
  return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Sean Bright
sumber
4
Ekspresi reguler adalah satu-satunya cara untuk mencapai "di luar kotak" ini tanpa menerapkan metode 'replaceAll' Anda sendiri. Saya tidak menyarankan penggunaannya hanya untuk menggunakannya.
Sean Bright
10
Ini adalah fungsi saya sendiri dari komentar ini: function replaceAll(find, replace,str) { var re = new RegExp(find, 'g'); str = str.replace(re, replace); return str; }
Klik Upvote
47
Peringatan utama dari replaceAllimplementasi adalah bahwa itu tidak akan berfungsi jika findmengandung karakter meta.
Martin Ender
1
@SeanBright Anda benar. Saya menggunakan javascript Anda dalam kode php jadi saya harus menambahkan backslash tambahan untuk melarikan diri. Pada biola kode Anda sempurna. Saya harus memeriksa. Permintaan maaf jsfiddle.net/7y19xyq8
Onimusha
2437

Demi kelengkapan, saya harus memikirkan metode apa yang harus saya gunakan untuk melakukan ini. Pada dasarnya ada dua cara untuk melakukan ini seperti yang disarankan oleh jawaban lain di halaman ini.

Catatan: Secara umum, memperluas prototipe bawaan dalam JavaScript umumnya tidak disarankan. Saya menyediakan ekstensi pada prototipe String hanya untuk tujuan ilustrasi, menunjukkan implementasi yang berbeda dari metode standar hipotetis Stringpada prototipe bawaan.


Implementasi Berbasis Ekspresi Reguler

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

Implementasi Split dan Bergabung (Fungsional)

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

Tidak tahu terlalu banyak tentang bagaimana ekspresi reguler bekerja di belakang layar dalam hal efisiensi, saya cenderung condong ke arah pemisahan dan bergabung dengan implementasi di masa lalu tanpa memikirkan kinerja. Ketika saya bertanya-tanya mana yang lebih efisien, dan berapa margin, saya menggunakannya sebagai alasan untuk mencari tahu.

Di mesin Chrome Windows 8 saya, implementasi berbasis ekspresi reguler adalah yang tercepat , dengan implementasi split dan join menjadi 53% lebih lambat . Berarti ekspresi reguler dua kali lebih cepat untuk input lorem ipsum yang saya gunakan.

Lihat patokan ini menjalankan dua implementasi ini terhadap satu sama lain.


Seperti dicatat dalam komentar di bawah ini oleh @ThomasLeduc dan lainnya, mungkin ada masalah dengan implementasi berbasis ekspresi reguler jika searchberisi karakter tertentu yang dicadangkan sebagai karakter khusus dalam ekspresi reguler . Implementasi mengasumsikan bahwa penelepon akan lolos string sebelumnya atau hanya akan melewati string yang tanpa karakter dalam tabel di Regular Expressions (MDN).

MDN juga menyediakan implementasi untuk keluar dari ikatan kami. Akan lebih baik jika ini juga dibakukan sebagai RegExp.escape(str), tapi sayangnya, itu tidak ada:

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

Kita bisa memanggil escapeRegExpdalam String.prototype.replaceAllimplementasi kami , namun, saya tidak yakin seberapa banyak ini akan mempengaruhi kinerja (bahkan potensial untuk string yang tidak diperlukan melarikan diri, seperti semua string alfanumerik).

Cory Gross
sumber
8
Pada Android 4.1 metode regexp adalah 15% lebih cepat, tetapi Anda tidak melarikan diri dari ekspresi untuk mencari, sehingga tolok ukur ini tidak lengkap.
andreszs
33
Ada masalah dengan solusi ini, jika string pencarian Anda tampaknya berisi karakter khusus dari ekspresi regexp, mereka akan ditafsirkan. Saya merekomendasikan jawaban @Sandy Unitedwolf.
Thomas Leduc
2
Yang pertama akan melakukan ini: 'bla.bla'.replaceAll ('. ',' _ '); "_______ Polandia". Yang kedua akan melakukan 'bla_bla', yang lebih umum apa yang ingin Anda lakukan.
RobKohr
1
@ThomasLeduc sepertinya masalah yang Anda sebutkan dapat diselesaikan dengan lodash => lodash.com/docs/4.17.5# escapeRegExp
Matthew Beck
1
Meninggalkan ini di sini untuk pemirsa di masa depan yang juga bertanya-tanya mengapa memperluas objek asli adalah ide yang buruk: stackoverflow.com/questions/14034180/...
Ben Cooper
692

Menggunakan ekspresi reguler dengan gset bendera akan menggantikan semua:

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

Lihat di sini juga

Adam A
sumber
15
Agak konyol saya pikir, tetapi JS global regex adalah satu-satunya cara untuk melakukan banyak penggantian.
Mike
5
baik secara teknis Anda dapat mengulang var sourceTextmenghitung jumlah instance (numOfInstances ) menggunakan substringatau membagi dan menghitung panjang (di antara strategi lain) thatWhichYouWantToReplacekemudian lakukan for (var i = 0; i < numOfInstances; i++){ sourceText = sourceText.replace('thatWhichYouWantToReplace', '');} atau bahkan lebih mudah hanya menggunakan loop sementara ( while sourceText.indexOf(thatWhichYouWantToReplace > -1){ sourceText = sourceText.replace(...)) tapi saya tidak melihat mengapa Anda ingin melakukannya dengan cara itu ketika menggunakan /gsangat mudah dan mungkin lebih banyak pemain.
Zargold
@ Zargold Anda ingin melakukan perulangan untuk memastikan bahwa bahkan setelah penggantian Anda telah mengganti semua instance, yang merupakan gotcha yang cukup umum. Lihat jawaban saya di bawah stackoverflow.com/a/26089052/87520
SamGoody
109

Inilah fungsi prototipe string berdasarkan jawaban yang diterima:

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

EDIT

Jika findkehendak Anda mengandung karakter khusus maka Anda perlu menghindarinya:

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

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

jesal
sumber
5
Tetapi bagaimana jika findberisi karakter seperti .atau $yang memiliki makna khusus di regex?
callum
1
@callum Dalam hal ini Anda harus keluar dari variabel find (lihat edit di atas).
jesal
Jesal, ini adalah solusi yang bagus untuk masalah penggantian string yang saya temui, dan tampaknya mengatasi "kekekalan" string dalam JavaScript. Bisakah Anda atau orang lain menjelaskan bagaimana fungsi prototipe ini menggantikan keabadian string? Ini tidak bekerja; Saya hanya ingin memahami pertanyaan tambahan yang diajukannya.
Tom
1
@ Tom: Itu tidak mengatasi sama sekali ketidakmampuan: var str = thismenciptakan referensi kedua ke string yang tidak dapat diubah, yang mana replacemetode ini diterapkan, yang pada gilirannya mengembalikan string yang tidak dapat diubah baru . fungsi prototipe ini mengembalikan string baru yang tidak dapat diubah, jika tidak, Anda akan dapat menulis someStrVar.replaceAll('o', '0');dan someStrVarakan diubah. Sebagai gantinya, Anda harus menulis someStrVar = someStrVar.replaceAll('o', '0');<- menugaskan kembali untuk mengatur var untuk memegang string baru yang tidak dapat diubah . tidak ada jalan lain untuk itu. Coba di konsol:x = 'foobar'; x.replaceAll('o', '0'); x;
Elias Van Ootegem
87

Memperbarui:

Agak terlambat untuk pembaruan, tetapi karena saya baru saja menemukan pertanyaan ini, dan memperhatikan bahwa jawaban saya sebelumnya bukanlah jawaban yang saya sukai. Karena pertanyaan melibatkan penggantian satu kata, sungguh luar biasa tidak ada yang berpikir untuk menggunakan batas kata ( \b)

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

Ini adalah regex sederhana yang menghindari penggantian bagian kata dalam kebanyakan kasus. Namun, tanda hubung -masih dianggap sebagai batas kata. Jadi kondisional dapat digunakan dalam kasus ini untuk menghindari penggantian string seperti 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"

pada dasarnya, pertanyaan ini sama dengan pertanyaan di sini: Javascript ganti "'" dengan "' '"

@ Mike, periksa jawaban yang saya berikan di sana ... regexp bukan satu-satunya cara untuk mengganti beberapa kemunculan subsrting, jauh dari itu. Berpikir fleksibel, pikirkan split!

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

Atau, untuk mencegah penggantian bagian kata - yang mana jawaban yang disetujui juga akan berlaku! Saya bisa mengatasi masalah ini menggunakan ekspresi reguler yang, saya akui, agak lebih kompleks dan sebagai hasilnya, sedikit lebih lambat, juga:

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

Outputnya sama dengan jawaban yang diterima, namun, menggunakan ekspresi / cat / g pada string ini:

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

Ups memang, ini mungkin bukan yang Anda inginkan. Apa itu? IMHO, sebuah regex yang hanya menggantikan 'kucing' dengan persyaratan. (Yaitu bukan bagian dari kata), seperti:

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"

Dugaan saya adalah, ini memenuhi kebutuhan Anda. Tentu saja, ini tidak sepenuhnya tahan, tetapi itu sudah cukup untuk Anda memulainya. Saya sarankan membaca lebih banyak di halaman-halaman ini. Ini terbukti bermanfaat dalam menyempurnakan ungkapan ini untuk memenuhi kebutuhan spesifik Anda.

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

http://www.regular-expressions.info


Penambahan akhir:

Mengingat bahwa pertanyaan ini masih mendapat banyak pandangan, saya pikir saya mungkin menambahkan contoh yang .replacedigunakan dengan fungsi panggilan balik. Dalam hal ini, ia secara dramatis menyederhanakan ekspresi dan bahkan memberikan lebih banyak fleksibilitas, seperti mengganti dengan huruf besar yang benar atau mengganti keduanya catdan catssekaligus:

'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
Elias Van Ootegem
sumber
Saya pikir bagian menarik tambahan harus ditempatkan di bagian bawah. ps .: Saya baru saja menyadari bahwa setengah dari baris pertama berada di luar area, izinkan saya memperbaikinya!
69

Cocokkan dengan ekspresi reguler global:

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

Untuk mengganti penggunaan satu kali:

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

Untuk mengganti beberapa kali gunakan:

var res = str.replace(/abc/g, "");
Indrajeet Singh
sumber
untuk seseorang yang perlu diganti \ n, Anda dapat melakukannya seperti:replace(/\n/g, '<br/>')
Phan Van Linh
58

Ini adalah metode yang paling umum dan mudah dibaca.

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

Metode 1:

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

Metode 2:

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

Metode 3:

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

Metode 4:

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

Keluaran:

console.log(str);
// Test replaced text test test replaced text test test test replaced text test test replaced text
Adnan Toky
sumber
44
str = str.replace(/abc/g, '');

Atau coba fungsi replaceAll dari sini:

Apa metode JavaScript yang berguna yang memperluas objek bawaan?

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

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

EDIT: Klarifikasi tentang replaceAll availability

Metode 'replaceAll' ditambahkan ke prototipe String. Ini berarti akan tersedia untuk semua objek string / literal.

Misalnya

var output = "test this".replaceAll('this', 'that');  //output is 'test that'.
output = output.replaceAll('that', 'this'); //output is 'test this'
SolutionYogi
sumber
2
Bisakah Anda menulis ulang fungsi replaceAll () di sana untuk mereka yang tidak menggunakan prototipe?
Klik Upvote
@Klik Upvote .... Anda menggunakan prototipe, ini adalah bagian dari semua objek JS. Saya pikir Anda berpikir tentang prototipe. JS perpustakaan JS.
seth
seth, sedikit koreksi. Jika Anda menambahkan metode ke prototipe, ini tersedia untuk semua objek jenis itu. Metode replceAll ditambahkan ke prototipe String dan harus bekerja untuk semua objek string.
SolutionYogi
@solutionyogi - Yap, saya telah menggunakan prototipe (dengan benar) sebelumnya. Saya hanya menanggapi komentar OP tentang "tidak menggunakan prototipe" yang saya anggap berarti Prototype.js (mungkin salah?). Saya seharusnya mengatakan "prototipe" ketika saya mencoba untuk mengatakan objek JavaScript memiliki prototipe. Jadi, OP sudah 'menggunakan prototipe,' meskipun dengan cara "tidak langsung". Tidak langsung mungkin istilah yang salah untuk digunakan di sini tapi saya lelah jadi saya culpa.
seth
41

Menggunakan RegExpdalam JavaScript dapat melakukan pekerjaan untuk Anda, cukup lakukan sesuatu seperti kode di bawah ini, jangan lupa /gsetelah yang menonjol untuk global :

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

Jika Anda berpikir untuk menggunakan kembali, buat fungsi untuk melakukannya untuk Anda, tetapi itu tidak disarankan karena hanya satu fungsi baris, tetapi sekali lagi jika Anda banyak menggunakan ini, Anda dapat menulis sesuatu seperti ini:

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

dan cukup gunakan dalam kode Anda berulang-ulang seperti di bawah ini:

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

Tetapi seperti yang saya sebutkan sebelumnya, itu tidak akan membuat perbedaan besar dalam hal baris untuk ditulis atau kinerja, hanya caching fungsi dapat mempengaruhi beberapa kinerja lebih cepat pada string panjang dan juga praktik yang baik dari kode KERING jika Anda ingin menggunakan kembali.

Alireza
sumber
40

Katakanlah Anda ingin mengganti semua 'abc' dengan '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

Saya mencoba untuk memikirkan sesuatu yang lebih sederhana daripada memodifikasi prototipe string.

Emilio Grisolía
sumber
1
Sederhana, mudah, dan mungkin opsi yang paling berkinerja: jawaban yang bagus.
machineghost
Sebenarnya, sementara saya belum metrik-ed secara pribadi, split / join biasanya merupakan solusi yang sangat performant.
machineghost
1
itu bahkan di chrome, 100% lebih cepat pada firefox, dan 50% lebih lambat pada IE ...: jsperf.com/replace-regex-split-join
Olivier
37

Gunakan ekspresi reguler:

str.replace(/abc/g, '');
Donnie DeBoer
sumber
32

Mengganti tanda kutip tunggal:

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

    return text;
}
Chris Rosete
sumber
2
Bagaimana saya bisa mengubah baris kedua untuk mengganti string? Ini tidak berfungsi: text = text.replace ('hey', 'hello'); Ada ide?
Stefan Đorđević
2
Tentu Stefan, ini kode ... text = text.replace (/ hey / g, 'hello');
Chris Rosete
26

// lilitkan sampai jumlah kejadian mencapai 0. ATAU cukup salin / tempel

    function replaceAll(find, replace, str) 
    {
      while( str.indexOf(find) > -1)
      {
        str = str.replace(find, replace);
      }
      return str;
    }
Raseela
sumber
23
Metode ini berbahaya, jangan gunakan itu. Jika string pengganti berisi kata kunci pencarian, maka loop infinite akan muncul. Paling tidak, simpan hasil .indexOfdalam variabel, dan gunakan variabel ini sebagai parameter kedua .indexOf(dikurangi panjang kata kunci, ditambah panjang string pengganti).
Rob W
Saya sedang berpikir tentang mengganti pola pencarian pertama dengan char unicode weired, itu kami yakin itu tidak digunakan dalam string input. Seperti U + E000 di area pribadi. Dan kemudian ganti kembali ke target. Saya membangunnya di sini. . Saya tidak yakin apakah itu Ide yang bagus.
Lux
26
str = str.replace(new RegExp("abc", 'g'), "");

bekerja lebih baik untuk saya daripada jawaban di atas. jadi new RegExp("abc", 'g')buat RegExp yang cocok dengan semua kemunculan ( 'g'bendera) teks ( "abc"). Bagian kedua adalah apa yang akan diganti, dalam kasus Anda string kosong ( ""). stradalah string, dan kita harus menimpanya, karena replace(...)hanya mengembalikan hasil, tetapi bukan menimpa. Dalam beberapa kasus, Anda mungkin ingin menggunakannya.

csomakk
sumber
Sementara cuplikan kode ini mungkin solusinya, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
yivi
Ya kamu benar. ditambahkan. juga mengeditnya untuk menjawab pertanyaan awal :)
csomakk
Catatan: g flag dalam regex berarti itu adalah flag global yang akan cocok dengan semua kemunculan
firstpostcommenter
25

Ini adalah versi tercepat yang tidak menggunakan ekspresi reguler .

JSPF direvisi

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

Ini hampir dua kali lebih cepat dari metode split dan join.

Seperti yang ditunjukkan dalam komentar di sini, ini tidak akan berfungsi jika omitvariabel Anda berisi place, seperti pada:, replaceAll("string", "s", "ss")karena itu akan selalu dapat menggantikan kemunculan kata lainnya.

Ada jsperf lain dengan varian pada rekursif saya yang lebih cepat ( http://jsperf.com/replace-all-vs-split-join/12 )!

  • Pembaruan 27 Juli 2017: Sepertinya RegExp sekarang memiliki kinerja tercepat di Chrome 59 yang baru dirilis.
Cole Lawrence
sumber
Saya menyukai solusi Anda ... Saya berharap saya bisa memberi Anda +10 tapi ini +1 saya. Saya pikir Anda dapat menyimpan indeks sub-string yang diganti dan melompat ke yang berikutnya jika kecocokan ditemukan pada indeks yang lebih rendah untuk menghindari masalah loop tak terbatas. Saya tidak dapat berkomentar tentang kinerja karena saya tidak mengujinya tetapi itu hanya 2 sen saya pada keunggulan ini.
Fr0zenFyr
@ fr0zenfyr jika Anda ingin memeriksa apakah menghilangkan ada di tempat (untuk mencegah loop tak terbatas) Anda bisa melakukan bersyarat seperti if(place.replace(omit) === omit) {Tidak cocok, jadi aman untuk menggunakan ganti loop } else {Cocokkan jadi gunakan metode yang berbeda seperti split dan bergabung}
Cole Lawrence
Hmm .. tapi apa gunanya menggabungkan dua solusi?
Lagi
@ Fr0zenFyr Saya percaya tujuan menggabungkan dua solusi adalah untuk mundur pada metode yang lebih lambat jika Anda tidak dapat menggunakan yang lebih cepat (ketika loop akan menjadi tak terbatas misalnya). Jadi itu akan menjadi penjaga yang aman untuk memastikan fungsionalitas dengan efisiensi, tetapi tanpa kemungkinan kegagalan.
Cole Lawrence
@ mama bagaimana cacatnya?
SandRock
24

Performa

Hari ini 27.12.2019 Saya melakukan tes pada macOS v10.13.6 (High Sierra) untuk solusi yang dipilih.

Kesimpulan

  • The str.replace(/abc/g, '');( C ) adalah cross-browser solusi cepat baik untuk semua string.
  • Solusi berdasarkan split-join( A, B ) atau replace( C, D ) cepat
  • Solusi berdasarkan while( E, F, G, H ) lambat - biasanya ~ 4 kali lebih lambat untuk string kecil dan sekitar ~ 3000 kali (!) Lebih lambat untuk string panjang
  • Solusi perulangan ( RA, RB ) lambat dan tidak bekerja untuk string panjang

Saya juga membuat solusi sendiri. Sepertinya saat ini adalah yang terpendek yang melakukan pekerjaan pertanyaan:

str.split`abc`.join``

Detail

Pengujian dilakukan pada Chrome 79.0, Safari 13.0.4 dan Firefox 71.0 (64 bit). Tes RAdan RBgunakan rekursi. Hasil

Masukkan deskripsi gambar di sini

String pendek - 55 karakter

Anda dapat menjalankan tes pada mesin Anda DI SINI . Hasil untuk Chrome:

Masukkan deskripsi gambar di sini

String panjang: 275 000 karakter

Solusi rekursif RA dan RB memberikan

RangeError: Ukuran tumpukan panggilan maksimum terlampaui

Untuk karakter 1M mereka bahkan memecahkan Chrome

masukkan deskripsi gambar di sini

Saya mencoba melakukan tes untuk 1M karakter untuk solusi lain, tetapi E, F, G, H membutuhkan banyak waktu sehingga browser meminta saya untuk memecahkan skrip jadi saya mengecilkan string uji menjadi 275 ribu karakter. Anda dapat menjalankan tes pada mesin Anda DI SINI . Hasil untuk Chrome

masukkan deskripsi gambar di sini

Kode yang digunakan dalam tes

Kamil Kiełczewski
sumber
1
Sekarang ini adalah jawaban yang sangat mendalam! Terima kasih banyak! Meskipun, yang saya ingin tahu tentang mengapa sintaks "RegExp (...)" baru memberikan banyak perbaikan.
Mark Gergely Dolinka
21

Jika yang ingin Anda temukan sudah ada dalam string, dan Anda tidak memiliki regex escaper berguna, Anda bisa menggunakan 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'));

rakslice
sumber
Terima kasih! Solusi ini berfungsi sempurna untuk masalah saya :)
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;
}
Tim Rivoli
sumber
Saya bertanya-tanya seberapa bagus performanya ... substring adalah asli atau berjalan di atas char array untuk membuat karakter baru.
mmm
16

Saya suka metode ini (kelihatannya sedikit lebih bersih):

text = text.replace(new RegExp("cat","g"), "dog"); 
Owen
sumber
1
Oke, bagaimana Anda lolos dari string untuk menggunakannya sebagai pola regex?
rakslice
Saya tidak, saya hanya menggunakannya untuk teks biasa
Owen
15

Cara paling sederhana untuk ini tanpa menggunakan regex apa pun dibagi dan bergabung seperti kode di sini:

var str = "Test abc test test abc test test test abc test test abc";
str.split('abc').join('')
sajadre
sumber
13
var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/

pkdkk
sumber
apa gunanya biola yang hanya berisi javascript yang sama
JGallardo
13
while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}
zdennis
sumber
13

Jika string berisi pola yang mirip seperti abccc, Anda dapat menggunakan ini:

str.replace(/abc(\s|$)/g, "")
mostafa elmadany
sumber
13

Jawaban sebelumnya terlalu rumit. Cukup gunakan fungsi ganti seperti ini:

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

Contoh:

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

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

console.log(res);

Hitam
sumber
10

Jika Anda mencoba memastikan bahwa string yang Anda cari tidak akan ada bahkan setelah penggantian, Anda perlu menggunakan loop.

Sebagai contoh:

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

Ketika selesai, Anda masih akan memiliki 'test abc'!

Loop paling sederhana untuk menyelesaikan ini adalah:

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

Tapi itu menjalankan penggantian dua kali untuk setiap siklus. Mungkin (beresiko ditolak) yang dapat digabungkan untuk bentuk yang sedikit lebih efisien tetapi kurang mudah dibaca:

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

Ini bisa sangat berguna saat mencari string duplikat.
Misalnya, jika kami memiliki 'a ,,, b' dan kami ingin menghapus semua koma rangkap.
[Dalam hal ini, seseorang bisa melakukan .replace (/, + / g, ','), tetapi pada titik tertentu regex menjadi kompleks dan cukup lambat untuk diulang.]

SamGoody
sumber
10

Meskipun orang telah menyebutkan penggunaan regex tetapi ada pendekatan yang lebih baik jika Anda ingin mengganti teks terlepas dari kasus teks. Seperti huruf besar atau kecil. Gunakan sintaksis di bawah ini

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

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

Anda dapat merujuk contoh terperinci di sini .

Kode Cheezy
sumber
dari situs contoh: "/ toBeReplacedString / gi adalah regex yang perlu Anda gunakan. Di sini g mewakili untuk pertandingan global dan saya mewakili case-sensitive. Secara default regex sensitif huruf"
alikuli
8

Anda cukup menggunakan metode di bawah ini

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

Cukup tambahkan /g

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

untuk

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

/g berarti global

Reza Fahmi
sumber