Javascript RegExp 用于精确匹配具有特殊字符的多个单词

Posted

技术标签:

【中文标题】Javascript RegExp 用于精确匹配具有特殊字符的多个单词【英文标题】:Javascript RegExp for exact multiple words with special characters match 【发布时间】:2021-09-28 10:49:37 【问题描述】:

我正在使用 RegExp 进行多个单词匹配。它具有动态值,因此当出现像“(”这样的特殊字符时,它会将其作为表达式并显示 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)

【问题讨论】:

您的文本包含一个特殊的正则表达式字符(。如果您希望所有文本都是文字,请先尝试escaping them。 【参考方案1】:

\b word boundary 匹配以下三个位置中的任何一个:

    在字符串的第一个字符之前,如果第一个字符是单词字符。 在字符串的最后一个字符之后,如果最后一个字符是单词字符。 字符串中两个字符之间,一个是单词字符,另一个不是单词字符。 您需要通用的单词边界,在搜索词之前需要一个非单词字符或字符串开头,在搜索字符串之后需要一个非单词字符或字符串结尾。

请注意,您还需要按长度降序对 findTerm 项目进行排序,以避免重叠术语问题。

最后,不要忘记转义要在正则表达式模式中使用的 findTerm 项。

你可以使用

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)

请注意,"&lt;mark&gt;$&amp;&lt;/mark&gt;"match =&gt; "&lt;mark&gt;" + match + "&lt;/mark&gt;" 的缩写形式,因为 $&amp; 是对字符串替换模式中整个匹配值的反向引用。

正则表达式是

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

或者

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

请参阅 regex #1 demo 和 regex #2 demo。 详情

(?:\B(?!\w)|\b(?=\w)) - 如果下一个字符不是单词字符,则为非单词边界,如果下一个字符是单词字符,则为单词边界 (?:(?!\w)|\b(?=\w)) - 下一个 char 必须是非单词 char,或者当前位置左侧必须没有单词 char,并且下一个必须是单词 char(如果术语以特殊字符开头,不需要边界) (?:\(not working text|working text) - 与findTerm 数组中设置的替代模式之一匹配的非捕获组 (?:(?&lt;=\w)\b|(?&lt;!\w)\B) - 如果前面的 char 是单词 char,则为单词边界;如果前面的 char 不是单词 char,则为非单词边界 (?:(?&lt;=\w)\b|(?&lt;!\w)) - 如果前一个 char 是 word char,则下一个不能是 word char,或者前一个 char 不应该是 word char(如果 term 以特殊 char 结尾,则不需要边界)李>

【讨论】:

它有效。如果我们不希望整个单词完全匹配,只需删除此 RegExp 中的 \b。 @PyRu 实际上,如果您不需要完全匹配,请删除 (?:\B(?!\w)|\b(?=\w))(?:(?&lt;=\w)\b|(?&lt;!\w)\B) 感谢您的回答。我接受了

以上是关于Javascript RegExp 用于精确匹配具有特殊字符的多个单词的主要内容,如果未能解决你的问题,请参考以下文章

MySQL REGEXP数字精确匹配不起作用

Rails Regexp::IGNORECASE 同时将精确选项与数字选项匹配也包含在结果中

JavaScript RegExp(正则表达式) 对象

JavaScript RegExp对象

弹性搜索查询在regexp输入参数的列表中查找值的精确匹配

JavaScript RegExp 对象