JavaScript - 将字符串与正则表达式数组进行匹配

74

在JavaScript中,是否有一种方法可以针对正则表达式数组中的字符串匹配获取布尔值?

例如('if'语句表示我想要实现的内容):

var thisExpressions = [ '/something/', '/something_else/', '/and_something_else/'];
var thisString = 'else';

if (matchInArray(thisString, thisExpressions)) {

} 

你是要匹配所有表达式(AND),还是任何一个表达式(OR)? - Arth
使用jQuery,您可以使用jQuery.inArray()函数。 - GillesC
10个回答

137

使用更加函数式的方法,你可以使用一个数组函数实现匹配:

ECMAScript 6:

const regexList = [/apple/, /pear/];
const text = "banana pear";
const isMatch = regexList.some(rx => rx.test(text));

ECMAScript 5:

var regexList = [/apple/, /pear/];
var text = "banana pear";
var isMatch = regexList.some(function(rx) { return rx.test(text); });

2
另外值得一提的是Arrayfilter方法,这个方法经常很有用而且使用方式相同。 - Sanjay Manohar
2
此外,如果您希望匹配数组中的所有内容,请使用.every,而不是返回数组中任何一个匹配项为true的.some函数。 - Michael Warner
1
这应该是现代 JavaScript 的推荐答案。 - DrCord

22

http://jsfiddle.net/9nyhh/1/

var thisExpressions = [/something/, /something_else/, /and_something_else/];
var thisExpressions2 = [/else/, /something_else/, /and_something_else/];
var thisString = 'else';

function matchInArray(string, expressions) {

    var len = expressions.length,
        i = 0;

    for (; i < len; i++) {
        if (string.match(expressions[i])) {
            return true;
        }
    }

    return false;

};

setTimeout(function() {
    console.log(matchInArray(thisString, thisExpressions));
    console.log(matchInArray(thisString, thisExpressions2));
}, 200)​

2
为什么不完全剥离res变量,在if语句中返回true,并在结尾处返回false。然后它将在找到第一个匹配项时退出。 - Arth
我会使用 expressions[i].test(string) 而不是 string.match()。 - Arth
2
尽管这段代码可能回答了问题,但提供有关为什么和/或如何回答问题的额外背景信息将显著改善其长期价值。请[编辑]您的答案以添加一些解释。 - Toby Speight
如果我想要匹配值的索引呢? - Si8

6
您可以使用.test(),当在另一个字符串中找到所需内容时返回布尔值:
var thisExpressions = [ '/something/', '/something_else/', '/and_something_else/'];
var thisString = new RegExp('\\b' + 'else' + '\\b', 'i');
var FoundIt = thisString.test(thisExpressions);  
if (FoundIt) { /* DO STUFF */ }

1
RegExp.prototype.test() 不能与数组一起使用,它需要一个字符串作为参数。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test - gdibble
1
@ gdibble,这将有效,因为test它在提供的参数上调用toString,对于数组来说,将调用join()。虽然可能不建议这样做! - WickyNilliams
/monkey/.test({ toString : () => "monkey" }) // true - WickyNilliams
@Likwid_T - '\b' 是什么意思?我知道 'i' 表示不区分大小写,但我在网上找不到 \b 的含义。另外,为什么你要用两次? - GK79
@WickyNilliams 好的,朋友;) - gdibble
1
@GK79 \b是一个单词边界,这意味着你可以在单词“roller”中匹配/\broller\b/,但它不会匹配“rollercoaster”,然而如果你去掉尾部的\b,那么它将匹配“rollercoaster”的第一部分。 - gdibble

2
考虑将此问题分为两个部分:
  1. 过滤掉与给定正则表达式匹配的项
  2. 确定该过滤列表中是否有0个匹配项
const sampleStringData = ["frog", "pig", "tiger"];

const matches = sampleStringData.filter((animal) => /any.regex.here/.test(animal));

if (matches.length === 0) {
  console.log("No matches");
}

1
你可以将所有正则表达式合并为一个。这样字符串只被扫描一次,即使使用稍微复杂的正则表达式。
var thisExpressions = [ /something/, /something_else/, /and_something_else/];
var thisString = 'else';


function matchInArray(str, expr) {
    var fullExpr = new RegExp(expr
        .map(x=>x.source) // Just if you need to provide RegExp instances instead of strings or ...
        // .map(x=>x.substring(1, x.length -2)  // ...if you need to provide strings enclosed by "/" like in original question.
        .join("|")
    )
    return str.match(fullExpr);

};


if (matchInArray(thisString, thisExpressions)) {
    console.log ("Match!!");
} 

事实上,即使使用这种方法,如果您需要针对多个字符串检查相同的表达式集,则会有一些次优,因为每次调用函数时都会构建(并编译)相同的正则表达式。
更好的方法是使用像这样的函数生成器:
var thisExpressions = [ /something/, /something_else/, /and_something_else/];
var thisString = 'else';

function matchInArray_builder(expr) {
    var fullExpr = new RegExp(expr
        .map(x=>x.source) // Just if you need to provide RegExp instances instead of strings or ...
        // .map(x=>x.substring(1, x.length -2)  // ...if you need to provide strings enclosed by "/" like in original question.
        .join("|")
    )   

    return function (str) {
        return str.match(fullExpr);

    };
};  

var matchInArray = matchInArray_builder(thisExpressions);

if (matchInArray(thisString)) {
    console.log ("Match!!");
} 

如果我想要匹配值的索引呢? - Si8
1
matchInArray(thisString, thisExpressions).index - bitifet
会不会在 var matchInArray = matchInArray_builder(thisExpressions); 之后加上这个:var matchInArray = matchInArray_builder(thisExpressions); var index = matchInArray(thisString, thisExpressions).index - Si8
不好意思,我不小心加了一个多余的参数。matchInArray() 函数返回 String.match() 的结果。因此,实际上“if”条件并不是一个布尔值,而是一个完整的结构(它会评估为 true),报告匹配的子字符串及其位置... - bitifet
啊啊啊啊...我在函数内误读了你的返回语句 :) - Si8
但这是必要的。否则,该函数将总是返回undefined(falsy);-) - bitifet

1

看这边...

function matchInArray(stringSearch, arrayExpressions){
    var position = String(arrayExpressions).search(stringSearch);
    var result = (position > -1) ? true : false
    return result;
}

1
尽管这段代码可能回答了问题,但提供关于它为什么和/或如何回答问题的额外背景信息将显著提高其长期价值。请编辑您的答案以添加一些解释。 - Toby Speight

1

如果你有全局标志,Andersh的解决方案将无法工作。
一个真正的返回值将在未来相同的测试中切换开和关。

regexArray.some( rx => rx.test( "a" ))    // true
regexArray.some( rx => rx.test( "a" ))    // false
regexArray.some( rx => rx.test( "a" ))    // true

(阅读此处了解详情)

这个方法可行,而且只需要一行代码:

const isMatch = regexList.map( rx => rx.source).includes( string )

.source 返回 RegExp 模式的文本字符串。
.map 返回这些字符串的数组。
.includes 返回字符串是否在数组中
(如果您需要索引,请使用 .indexOf

或者:

function isInsideArray( string, regexArray ){
  return regexArray.map( regex => regex.source).includes( string )
}

function isInsideArray_Andersh( string, regexArray ){
  return regexArray.some( rx => rx.test( string )) 
}

    
const list_rx = [ /apple/g, /pear/g, /banana/g ],
      string  = "pear"

console.log( isInsideArray( string, list_rx ))
console.log( 'Andersh:', isInsideArray_Andersh( string, list_rx ))
console.log( 'Andersh (same test):', isInsideArray_Andersh( string, list_rx ))


0
如果您想使用 String.match(),并且您的数组包含匹配字符串和正则表达式,则可以执行以下操作:
let str = "The quick brown fox";
let matches = ["fox", "The.*fox", /the.*fox/i];
let strInMatches = matches.some(match => str.match(match));
console.log(strInMatches);

0
let expressions = [ '/something/', '/something_else/', '/and_something_else/'];

let str = 'else';

这里将检查以下表达式:

if( expressions.find(expression => expression.includes(str) ) ) {

}

使用数组的 .find() 方法遍历数组,使用 .include() 方法检查子字符串。

-2
我们可以编写一个函数,该函数接受一个字符串和要查找的数组作为参数,并返回一个包含所有匹配项的新数组。在函数内部,我们创建一个新的正则表达式对象,然后对数组中的每个元素执行 String.search 操作。如果找到匹配项,则将其添加到新数组中并返回。
// literal_string: a regex search, like /thisword/ig
// target_arr: the array you want to search /thisword/ig for.

function arr_grep(literal_string, target_arr) {
  var match_bin = [];
  // o_regex: a new regex object.
  var o_regex = new RegExp(literal_string);
  for (var i = 0; i < target_arr.length; i++) {
    //loop through array. regex search each element.
    var test = String(target_arr[i]).search(o_regex);
    if (test > -1) {
    // if found push the element@index into our matchbin.
    match_bin.push(target_arr[i]);
    }
  }
  return match_bin;
}

// arr_grep(/.*this_word.*/ig, someArray)

考虑到问题的简单性,这种解决方案过于复杂。 - Es Noguera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接