【问题标题】:regex javascript - match multiple search terms ignoring their order正则表达式 javascript - 匹配多个搜索词忽略它们的顺序
【发布时间】:2021-10-26 17:06:51
【问题描述】:

我想在一个字符串中查找给定字符串(除以空格)的所有匹配项。 (例如,iTunes 搜索框的工作方式)。

例如,“ab de”和“de ab”都将在“abcde”上返回true(也是“bc ea" 或任何订单都应返回 true)

如果我用通配符替换空格,“ab*de”将在“abcde”上返回真,但不是“de*ab”。 [我使用 * 而不是 Regex 语法只是为了解释]

我找不到任何纯正则表达式解决方案。 我能想到的唯一解决方案是拆分搜索词并运行多个正则表达式。

是否有可能找到一个涵盖所有这些选项的纯正则表达式?

【问题讨论】:

  • 为什么? 这并不是正则表达式的设计初衷,那么你为什么要把它硬塞进正则表达式呢?只需单独搜索每个字符串。
  • 为什么ab*de 匹配abcde 在哪里?此外,模式ad de 是否也适用于给定短语ad hominem(因为找到ad)?星号是什么意思:应该匹配所有前面的非空白字符,还是只匹配前面的字符?
  • @Amber :我只是在想纯正则表达式会更快。我使用此搜索动态过滤结果以获取下拉列表。所以它必须很快。
  • 我很确定没有任何纯正则表达式解决方案。 Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems. - Jamie Zawinski
  • @Rob W:我的错。我解决了我的问题(它是“abcde”中的“abde”)。是的,“”表示所有非空白字符都应该匹配。

标签: javascript regex


【解决方案1】:

searchString 的所有部分(除以,' ')出现在文本中时,返回true。否则返回false

filter(text, searchString) {
    const regexStr = '(?=.*' + searchString.split(/\,|\s/).join(')(?=.*') + ')';
    const searchRegEx = new RegExp(regexStr, 'gi');
    return text.match(searchRegEx) !== null;
}

【讨论】:

  • 好主意! 从@RoccoC5 升级而来的答案在这里:stackoverflow.com/a/8809030/7514010 - 我认为你最好将.* 更改为[^]* 以使其也支持新行。并且使用RegExp.prototype.test() 更准确。示例:regexr.com/67ldq 只是经过逻辑测试和测试,对于像段落这样的大字符串,它性能低
【解决方案2】:

这是我使用的脚本 - 它也适用于单个单词 searchStrings

var what="test string with search cool word";
var searchString="search word";
var search = new RegExp(searchString, "gi"); // one-word searching

// multiple search words
if(searchString.indexOf(' ') != -1) {

    search="";
    var words=searchString.split(" ");

    for(var i = 0; i < words.length; i++) {

        search+="(?=.*" + words[i] + ")";

    }

    search = new RegExp(search + ".+", "gi");

}

if(search.test(what)) {

    // found

} else {

    // notfound

}

【讨论】:

    【解决方案3】:

    交替不区分顺序:

    "abcde".match(/(ab|de)/g); // => ['ab', 'de']
    "abcde".match(/(de|ab)/g); // => ['ab', 'de']
    

    因此,如果您有要匹配的单词列表,则可以像这样动态地构建一个带有交替的正则表达式:

    function regexForWordList(words) {
      return new RegExp('(' + words.join('|') + ')', 'g');
    }
    'abcde'.match(['a', 'e']); // => ['a', 'e']
    

    【讨论】:

    • 这称为交替条件更复杂(ref)。
    • 这是一个不错的方法,但是当任何一个单词('ab' OR 'de')在匹配的字符串中时,它将返回 true。我希望它只有在找到“ab”和“de”时才返回 true。
    • 然后检查匹配数组中是否同时找到了'ab'和'de'?
    【解决方案4】:

    试试这个:

    var str = "your string";
    str = str.split( " " );
    for( var i = 0 ; i < str.length ; i++ ){
        // your regexp match
    }
    

    【讨论】:

    • 嗯,我在问是否有一个纯正则表达式解决方案......猜不
    • ic 尚未声明。除此之外,您为什么要针对数组检查c?拆分总是返回一个数组,如果没有找到字符则包含一个元素,如果字符串为空则包含零个元素。
    • @RobW 你是对的。该死的,完全没有注意到...现在编辑。
    • str.split( " " ) 会创建一个数组,即使 str 中没有空格
    • @qwertymk 这就是为什么在您发表评论前 5 分钟编辑了答案 =)
    【解决方案5】:

    我假设您正在匹配单词或单词的一部分。您希望以空格分隔的搜索词来限制搜索结果,并且您似乎打算只返回那些包含用户提供的所有词的条目。并且您希望通配符 * 代表匹配单词中的 0 个或多个字符。

    例如,如果用户搜索词 term1 term2,您打算只返回那些具有两个词 term1 的项目em>term2。如果用户搜索单词 term*,它将匹配任何以 term 开头的单词。

    有合适的正则表达式等价于这种搜索语言,可以从中生成。

    一个简单的例子,单词term,可以在正则表达式中通过转换为\bterm\b来断言。但是必须以任何顺序匹配的两个或多个单词需要先行断言。使用扩展语法,等效的正则表达式为:

    (?= .* \b term1 \b )
    (?= .* \b term2 \b )
    

    星号通配符可以在正则表达式中使用字符类后跟星号进行断言。字符类标识您认为哪些字母是单词的一部分。例如,您可能会发现 [A-Za-z0-9]* 符合要求。

    简而言之,如果您转换如下表达式,您可能会感到满意:

    foo ba* quux
    

    到:

    (?= .* \b foo            \b )
    (?= .* \b ba[A-Za-z0-9]* \b )
    (?= .* \b quux           \b )
    

    这是一个简单的搜索和替换问题。但请注意清理输入字符串,以避免通过删除标点符号等进行注入攻击。

    【讨论】:

      【解决方案6】:

      我认为您可能使用 RegEx 找错了树。您可能想查看的是两个输入字符串的Levenshtein distance

      有一个 Javascript 实现 here 和一个用法示例 here

      【讨论】:

      • 这不是他想要的。该演示显示apple pearpear apple(带有两个空格)与apple pearpear orange 具有相同的距离...
      【解决方案7】:

      我很确定你可以想出一个正则表达式来做你想做的事,但这可能不是最有效的方法。

      例如,正则表达式模式(?=.*bc)(?=.*e)(?=.*a) 将匹配包含bce a 的任何字符串。

      var isMatch = 'abcde'.match(/(?=.*bc)(?=.*e)(?=.*a)/) != null; // equals true
      
      var isMatch = 'bcde'.match(/(?=.*bc)(?=.*e)(?=.*a)/) != null; // equals false
      

      您可以编写一个函数来根据您的搜索词动态创建表达式,但它是否是完成您正在做的事情的最佳方式是另一个问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-25
        • 2022-10-07
        • 2014-04-17
        • 1970-01-01
        • 2014-08-05
        • 1970-01-01
        • 2021-03-14
        相关资源
        最近更新 更多