代码之家  ›  专栏  ›  技术社区  ›  johnny_mac

带有可选非文字字符的Javascript正则表达式文字边界

  •  1
  • johnny_mac  · 技术社区  · 7 年前

    ['hello', '#hello', '@hello'];
    

    这是我的代码,其中包括在 post :

    let userStr = 'why hello there, or should I say #hello there?';
    
    let keyword = '#hello';
    
    let re = new RegExp(`/(#\b${userStr})\b/`);
    
    re.exec(keyword);
    
    • 如果字符串总是以#开头,这将非常好,但它不是。
    • 然后我试了一下 /(#?\b${userStr})\b/ ,但如果字符串以开头 # ,它试图匹配 ##hello .
    • 这个 matchThis str可以是数组中3个示例中的任意一个,userStr可以包含 匹配此 但只有一个是准确的
    2 回复  |  直到 7 年前
        1
  •  1
  •   Wiktor Stribiżew    7 年前

    你需要在这里说明三件事:

    • \b 单词边界是一个上下文相关的构造,如果您的输入不总是仅为字母数字,则需要明确的单词边界
    • 您需要在构造函数RegExp符号内对特殊字符进行双转义
    • 在将变量传递给正则表达式时,需要确保所有特殊字符都正确转义。

    使用

    let userStr = 'why hello there, or should I say #hello there?';
    let keyword = '#hello';
    let re_pattern = `(?:^|\\W)(${keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')})(?!\\w)`;
    let res = [], m;
    
    // To find a single (first) match
    console.log((m=new RegExp(re_pattern).exec(userStr)) ? m[1] : "");
    
    // To find multiple matches:
    let rx = new RegExp(re_pattern, "g");
    while (m=rx.exec(userStr)) {
        res.push(m[1]);
    }
    console.log(res);

    图案描述

    • (?:^|\\W) -与字符串或任何非文字字符开头匹配的非捕获字符串
    • (${keyword.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}) -第1组:a 关键字 带转义特殊字符的值
    • (?!\\w) -如果当前位置右侧有一个单词char,则会导致匹配失败的负前瞻。
        2
  •  -1
  •   Barmar    7 年前

    检查关键字是否已以特殊字符开头。如果是,请不要将其包含在正则表达式中。

    var re;
    if ("#@".indexOf(keyword[0]) == -1) {
        re = new RegExp(`[@#]?\b${keyword}\b`);
    } else {
        re = new RegExp(`\b${keyword}\b`);
    }