【问题标题】:RegExp case insensitive search for whole word with variable正则表达式不区分大小写搜索带有变量的整个单词
【发布时间】:2016-10-07 21:04:07
【问题描述】:

我有一个带有字符串属性的对象,我想使用不区分大小写的方式与多个用户输入进行比较。我的目标是将输入字符串与对象字符串匹配,以将关联值增加 1(如果匹配)。

var objArr = [
    {"O": 0},
    {"foo": 0},
    {"faa": 0},
    {"A": 0}
];

除了不区分大小写之外,一切都很顺利。我使用的 RegExp 方法只查找一个字母而不是整个单词。我可能没有使用正确的语法,但我在 google 上找不到解释 /i 标志和变量的结果。 我最接近的尝试是:

var re = new RegExp(b, "i"); //problem here 
if (allinputs[i].value.match(re)) { //and here

此代码确实允许不区分大小写,但它不会查找整个对象属性字符串并停止查找字母。例如,键入“foo”将导致与“O”匹配,因为它包含字母“O”,并且属性“O”在“foo”之前。因此,键入“faa”匹配“faa”而不是“A”,因为“faa”在对象数组中位于“A”之前。我的对象中不存在的字符串(如“asfo”)仍将与“O”匹配,因为只有一个常见字母。

有没有办法使用 regExp /i flag 搜索 整个 不区分大小写的属性字符串?如果可能,我想避免使用 .toUpperCase() 或 .toLowerCase() 方法。

在这里提琴:https://jsfiddle.net/Lau1989/b39Luhcu/

感谢您的帮助

【问题讨论】:

    标签: javascript regex


    【解决方案1】:

    要检查正则表达式是否匹配整个字符串,您可以使用断言开始字符 (^) 和断言结束字符 ($)。

    例如,hello 匹配 e,但不匹配 ^e$

    对于您的代码,只需将^ 添加到正则表达式并附加$

    var re = new RegExp("^" + b + "$", "i");
    

    fiddle

    编辑:某些字符在正则表达式中具有特殊含义(^$\.* 等)。如果您需要使用这些字符中的任何一个,应使用\ 对它们进行转义。为此,您可以使用这个简单的替换:

    str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    

    所以,你的正则表达式最终会是

    new RegExp("^" + b.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + "$", "i");
    

    有关转义正则表达式的更多信息,请参阅this question


    您也可以将两个字符串转换为小写,然后直接比较它们。这也将允许您使用特殊字符。

    if (stringA.toLowerCase() == stringB.toLowerCase())) {
        ...
    }
    

    【讨论】:

    • 谢谢,您的第一个解决方案非常有效。不过还有最后一个问题:我正在尝试支持 '+' 和 '()' 字符检测,同时忽略 '/' 字符。我试图添加'\。'到正则表达式,但它似乎不起作用。知道我应该怎么做吗? jsfiddle.net/Lau1989/auue3xb3/2
    • 非常感谢。像这样的复杂正则表达式对我来说仍然有点困惑,所以我会花一些时间来更好地理解你是如何“构建”它们的。但是,您的解决方案效果很好。
    • 老实说,在这种情况下,您最好转换为小写并检查字符串是否匹配(我的答案的第二部分)。使用正则表达式的唯一原因是如果您想使用那些现在被过滤掉的特殊字符。
    【解决方案2】:

    您的方法几乎是正确的,但您需要限制正则表达式以避免使用 ^(字符串开头)和 $(字符串结尾)进行任何匹配。

    这是我制作的可能适合您需要的代码:

    function process() {

    var allinputs = document.querySelectorAll('input[type="text"]');
    var list = new Array();
    var input = "";
    
    objArr.map(function(value, index, array){ list.push(Object.keys(value))})
    
    for(var i = 0; i < allinputs.length; i++)
    {
         input = allinputs[i];
         if(input.value)
         {
              list.map(function( item, index, array ) {
                  var re = new RegExp("^"+input.value+"$", "i");
                  if(item.toString().match(re))
                  {
                      allinputs[i].value = "1";
                      objArr[index][item] += 1;
              allinputs[i].style.backgroundColor = "lime";
                      document.getElementById('output').innerHTML += item + " : " + objArr[index][item] + "<br />";
                   }
             });
         }
      }
    

    }

    这里的第一件事是从您的objArr 创建一个密钥列表,以便我们可以轻松访问密钥名称以匹配您键入的内容

      objArr.map(function(value, index, array){ list.push(Object.keys(value))})
    

    然后逻辑仍然和你已经做的一样,所有输入中的一个 for 循环。不同之处在于匹配将发生在list 数组而不是objArr 上。由于listobjArr的索引顺序相同,可以访问对象值进行递增。

    我在 list 数组中使用了 .map() 函数,如果您愿意,也可以使用 for 循环,这两种方法都可以。

    希望对你有帮助!

    【讨论】:

    • 非常感谢您教我一种新的方法来处理这个问题。我仍在努力寻找正确的语法以支持“+”和“()”字符检测,同时忽略“/”字符。我可能会阅读任何想法或教程?再次感谢您的帮助
    • 网上有很多关于RegEx的解释,你可以开始看regexone.com。很难解释 RegEx 中的 () 和 +,但假设 () 将帮助您对匹配模式进行分组,而 + 信号表示“一次或多次”匹配它之前的匹配。例如:(a|b)+,你可以将这句话字面理解为:a or b one or more times,换句话说,任何有一个或多个 a 或 b 的模式都将匹配 RegEx。不要混淆 JS 中表示字符串连接的 + 信号。我希望这有助于您了解更多关于 RegEx 的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多