Reputation: 885
I have this string:
hello world hello world hello world hello
and I need to get the following:
hello world hello hello hello
If I use:
str = str.replace('world', '');
it only removes the first occurrence of world
in the above string.
How can I replace all the occurrences of it except the first one?
Upvotes: 15
Views: 7602
Reputation: 18490
Without additional function or lookarounds it can be done by using a variation of The Trick.
let str = 'hello world hello world hello world hello';
str = str.replace(/^(.*?world)|world/g, '$1');
console.log(str);
The part from ^
start until the first occurance of world
(lazy .*?
between) gets captured by group one |
OR any remaining world
s are normally matched. In this case the "trick" is to capture what is needed on the left side of the alternation |
but match what is not needed on the right.
Replacement is $1
and contains the substing until the first world
if the left side succeeded. Else if the right side matched, the first group would be empty - hence world
gets removed.
Since nowadays lookbehind is available in JS regex, another idea is to replace (world)(?<=\1.+)
with empty. It checks if the capture occurs before in the string and is not necessarily more efficient.
Upvotes: 1
Reputation: 4778
You can pass a function to String#replace, where you can specify to omit replacing the first occurrence. Also make your first parameter of replace a regex to match all occurrences.
Demo
let str = 'hello world hello world hello world hello',
i = 0;
str = str.replace(/world/g, m => !i++ ? m : '');
console.log(str);
Note
You could avoid using the global counter variable i
by using a IIFE:
let str = 'hello world hello world hello world hello';
str = str.replace(/world/g, (i => m => !i++ ? m : '')(0));
console.log(str);
Upvotes: 20
Reputation: 40404
To provide an alternative to @Kristianmitk excellent answer, we can use a positive lookbehind, which is supported in Node.Js & Chrome >= 62
const string = 'hello world hello world hello world hello';
console.log(
string.replace(/(?<=world[\s\S]+)world/g, '')
);
// or
console.log(
string.replace(/(?<=(world)[\s\S]+)\1/g, '')
);
Using Symbol.replace well-known symbol.
The Symbol.replace well-known symbol specifies the method that replaces matched substrings of a string. This function is called by the String.prototype.replace() method.
const string = 'hello world hello world hello world hello';
class ReplaceButFirst {
constructor(word, replace = '') {
this.count = 0;
this.replace = replace;
this.pattern = new RegExp(word, 'g');
}
[Symbol.replace](str) {
return str.replace(this.pattern, m => !this.count++ ? m : this.replace);
}
}
console.log(
string.replace(new ReplaceButFirst('world'))
);
Upvotes: 3
Reputation: 22885
In my solution, I am replacing first occurrence with a current timestamp, then replacing all occurrences and then finally replacing timestamp with world
You can also use str.split('world')
and then join
var str = 'hello world hello world hello world hello';
var strs = str.split('world');
str = strs[0] + 'world' + strs.slice(1).join('');
console.log(str);
var str = 'hello world hello world hello world hello';
const d = Date.now()
str = str.replace('world', d).replace(/world/gi, '').replace(d, 'world');
console.log(str);
Upvotes: 1
Reputation: 733
var str = 'hello world hello world hello world hello';
var count = 0;
var result = str.replace(/world/gi, function (x) {
if(count == 0) {
count++;
return x;
} else {
return '';
}
});
console.log(result);
Upvotes: 1
Reputation: 64657
I would do it like this:
function replaceExceptFirst(str, search) {
let index = str.indexOf(search);
return str.substring(0, index + search.length) +
str.substring(index + search.length).replace(/world/g, '')
}
console.log(replaceExceptFirst('hello world hello world world hello', 'world'))
Upvotes: 0