3

I'm trying to find a way to replace nth match of more matches lite this.

string = "one two three one one"

How do I target the second occurence of "one"?

Is it possible to do something like this?

string.replace(/\bone\b/gi{2}, "(one)")

to get something like this

"one two three (one) one"

I've done a jsfiddle which is working but it doesn't feel right. Heaps of code and confusing for a simple thing.

https://jsfiddle.net/Rickii/7u7pLqfd/

2 Answers2

2

Update :

To make it dynamic use this:

((?:.*?one.*?){1}.*?)one

where the value 1 means (n-1); which in your case is n=2

and replace by:

$1\(one\)

Regex101 Demo

const regex = /((?:.*?one.*?){1}.*?)one/m;
const str = `one two three one one asdfasdf one asdfasdf sdf one`;
const subst = `$1\(one\)`;
const result = str.replace(regex, subst);
console.log( result);
Mustofa Rizwan
  • 10,215
  • 2
  • 28
  • 43
  • Hey, this works too `((?:.*?one.*?){1})one` I just removed **.*?** after {1} from your solution, can you please tell me if it's wrong? – Aashit Garodia Jul 11 '21 at 18:59
2

A more general approach would be to use the replacer function.

// Replace the n-th occurrence of "re" in "input" using "transform"
function replaceNth(input, re, n, transform) {
  let count = 0;

  return input.replace(
    re, 
    match => n(++count) ? transform(match) : match);
}

console.log(replaceNth(
  "one two three one one", 
  /\bone\b/gi,
  count => count ===2,
  str => `(${str})`
));

// Capitalize even-numbered words.
console.log(replaceNth(
  "Now is the time",
  /\w+/g,
  count => !(count % 2),
  str => str.toUpperCase()));