Reputation: 1195
In JavaScript, I am using the below code to replace text that matches a certain string. The replacement wraps the string like this: "A(hello)"
. It works great but if there are two strings that are the same, for example: "Hello hi Hello"
, only the first one will get marked and if I am trying twice, it will get marked double, like this: "A(A(Hello)) Hi Hello"
.
A solution to this could be to not replace a word if it contains "A("
or is between "A("
and ")"
; both would work.
Any idea how it can be achieved?
Note: I cant use replaceAll because if there is already a word that is replaced and a new word is added, then the first one will be overwritten. Therefore I need a solution like above. For example,If I have a string saying "Hello hi", and I mark Hello, it will say "A(Hello) hi", but if I then add Hello again to the text and replace it, it will look like this: A(A(Hello)) hi A(Hello)
.
Here is what I got so far:
let text = "Hello hi Hello!"
let selection = "Hello"
let A = `A(${selection})`
let addWoman = text.replace(selection, A)
Upvotes: 2
Views: 1027
Reputation: 626738
A solution to this could be to not replace a word if it contains "A(" or is between "A(" and ")"; both would work.
To avoid re-matching selection
inside a A(...)
string, you can match A(...)
and capture it into a group so as to know if the group matched, it should be kept, else, match the word of your choice:
let text = "Hello hi Hello!"
let selection = "Hello"
let A = `A(${selection})`
const rx = new RegExp(String.raw`(A\([^()]*\))|${selection.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}`, 'g')
let addWoman = text.replace(rx, (x,y) => y || A)
console.log(addWoman);
// Replacing the second time does not modify the string:
console.log(addWoman.replace(rx, (x,y) => y || A))
The regex will look like /(A\([^()]*\))|Hello/g
, it matches
(A\([^()]*\))
- Group 1: A
and then (
followed with zero or more chars other than (
and )
and then a )
char|
- orHello
- a Hello
string.Upvotes: 1
Reputation: 784998
You can use a negative lookahead assertion in your pattern that fails the match if we A(
before full word Hello
:
(?<!A\()\bHello\b
And replace it with A($&)
Code:
let text = "Hello hi Hello!";
let selection = "Hello";
let A = `A(${selection})`;
let re = new RegExp(`(?<!A\\()\\b${selection}\\b`, "g");
let addWoman = text.replace(re, A);
console.log(addWoman);
console.log(addWoman.replace(re, A));
Upvotes: 3