首页 > 解决方案 > Safari 上的正则表达式错误。? 前面的token是不可量化的

问题描述

在 Safari 中执行正则表达式时,我收到错误“?前面的令牌不可量化”:

const replaceWord = (word, highlightColor) => {
    return `<span style='color: ${highlightColor} !important; font-weight: bold !important;'>${word}</span>`;
};

let message = `masterworld worldwide world business businesses
  <br />
  Gamification_in_the.Business.World.html
  <br />
  Gamification_in_the_Business>World.html
  <br/ >
  Gamification_in_the_Business_World.html
  <br />
  Gamification-in-the-Business-World.html`;

message = message.replace(
    // it was like this before: /* /\bbusiness\b|\bworld\b/gi, */
    // but since it need also to match business_world as two words, I changed to:
    /(?<![^\W_])business(?![^\W_])|(?<![^\W_])world(?![^\W_])/gi,
    (matched, offset, text) => {
        if (matched) {
            return replaceWord(matched, 'red');
        }
        return "";
    }
);

document.write(message);

但它在 Safari 上被打破了。我得到“?前面的令牌是不可量化的”

https://regex101.com/r/JpmF92/1

是否有等效的正则表达式让我在文本中搜索单词并将 _(下划线)视为分隔符?

在搜索“商业世界”时,我应该得到:

Business.World = match
Business_World = match
Business-World = match
Business>World = match
Business+World = match
businessworld = NO match

标签: javascriptregexhighlight

解决方案


正确,为了解决这个问题,在替换时,您需要使用匹配反向上下文的捕获组。在替换中,您需要添加的只是反向引用。

请参阅此 JavaScript 演示:

let message = "masterworld worldwide world business businesses<br />Gamification_in_the.Business.World.html<br />Gamification_in_the_Business>World.html<br/ >Gamification_in_the_Business_World.html<br />Gamification-in-the-Business-World.html";
message = message.replace(
    /([\W_]|^)(business|world)(?![^\W_])/gi,
    "$1<span style='color: red !important; font-weight: bold !important;'>$2</span>"
);
document.body.innerHTML = message;

现在,模式看起来像([\W_]|^)(business|world)(?![^\W_])

  • ([\W_]|^)- 第 1 组 ( $1):非单词字符或下划线或字符串开头
  • (business|world)- 第 2 组:两个词之一
  • (?![^\W_])- 检查下一个字符是否为非单词或_.

现在,在替换模式中,$1指的是捕获到组 1 中的字符(边界字符或字符串的开头),并$2指的是捕获到组 2 中的单词。

如果您想使用回调函数保留替换逻辑,您需要记住捕获的值也需要传递给该函数:

const replaceWord = (left, word, highlightColor) => {
    return `${left}<span style='color: ${highlightColor} !important; font-weight: bold !important;'>${word}</span>`;
};

let message = "masterworld worldwide world business businesses<br />Gamification_in_the.Business.World.html<br />Gamification_in_the_Business>World.html<br/ >Gamification_in_the_Business_World.html<br />Gamification-in-the-Business-World.html";

message = message.replace(
    /([\W_]|^)(business|world)(?![^\W_])/gi,
    (matched, group1, group2, offset, text) => {
        return replaceWord(group1, group2, 'red');
    }
);
document.body.innerHTML = message;

笔记:

  • if (matched)没有意义,如果代码进入回调函数总是有匹配的(只有在匹配时才会调用它)
  • (matched, group1, group2, offset, text) => return replaceWord(group1, group2, 'red')现在具有组值,并且group1是左侧上下文并且group2是您匹配的word.
  • replacedWordnowleft也接受参数,并且返回值以left文本为前缀。

推荐阅读