Javascript RegExp for exact multiple words with special characters match

I’m using RegExp for multiple words match. It has dynamic values so when a special character like "(" comes it takes that as an expression and shows Uncaught SyntaxError: Invalid regular expression error.

let text = 'working text and (not working text'
let findTerm = ['working text', '(not working text']
let replaceFromRegExp = new RegExp('\\b'+`(${findTerm.join("|")})`+'\\b', 'g')
text = text.replace(replaceFromRegExp, match => "<mark>" + match + "</mark>")
console.log(text)

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

A \b word boundary matches any of the following three positions:

  1. Before the first character in the string, if the first character is a word character.
  2. After the last character in the string, if the last character is a word character.
  3. Between two characters in the string, where one is a word character and the other is not a word character.
    You need universal word boundaries that will require a non-word char or start of string before a search word, and a non-word char or end of string after a search string.

Note you need to also sort the findTerm items in the descending order by length to avoid overlapping term issues.

Finally, do not forget to escape the findTerm items to be used in a regex pattern.

You can use

let text = 'working text and (not working text'
let findTerm = ['working text', '(not working text']
findTerm.sort((a, b) => b.length - a.length);
let replaceFromRegExp = new RegExp(String.raw`(?:\B(?!\w)|\b(?=\w))(?:${findTerm.map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join("|")})(?:(?<=\w)\b|(?<!\w)\B)`, 'g')
// If the boundaries for special chars should not be checked remove \B:
// let replaceFromRegExp = new RegExp(String.raw`(?:(?!\w)|\b(?=\w))(?:${findTerm.map(x => x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')).join("|")})(?:(?<=\w)\b|(?<!\w))`, 'g')
console.log(replaceFromRegExp)
text = text.replace(replaceFromRegExp, "<mark>$&</mark>")
console.log(text)

Note that "<mark>$&</mark>" is a shorter way of saying match => "<mark>" + match + "</mark>", as $& is a backreference to the whole match value in a string replacement pattern.

The regex is

/(?:\B(?!\w)|\b(?=\w))(?:\(not working text|working text)(?:(?<=\w)\b|(?<!\w)\B)/g

Or

/(?:(?!\w)|\b(?=\w))(?:\(not working text|working text)(?:(?<=\w)\b|(?<!\w))/g

See the regex #1 demo and the regex #2 demo. Details:

  • (?:\B(?!\w)|\b(?=\w)) – either a non-word boundary if the next char is not a word char, or a word boundary if the next char is a word char
  • (?:(?!\w)|\b(?=\w)) – either the next char must be a non-word char, or there must be no word char immediately to the left of the current location, and the next one must be a word char (if the term starts with a special char, no boundary is required)
  • (?:\(not working text|working text) – a non-capturing group matching one of the alternative patterns set in the findTerm array
  • (?:(?<=\w)\b|(?<!\w)\B) – either a word boundary if the preceding char is a word char, or a non-word boundary if the preceding char is not a word char
  • (?:(?<=\w)\b|(?<!\w)) – if the previous char is a word char, the next one must not be a word char, or the previous char should not be a word char (if the term ends with a special char, no boundary is required)

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply