我想使用正则表达式匹配字符串的一部分,然后访问带括号的子字符串:

var myString=“something format_abc”;//我要“abc”var arr=/(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);控制台日志(arr);//打印:[“format_abc”,“abc”]。。到现在为止,一直都还不错。控制台日志(arr[1]);//打印:未定义(???)控制台日志(arr[0]);//打印:format_undefined(!!!)

我做错了什么?


我发现上面的正则表达式代码没有任何问题:我测试的实际字符串是这样的:

"date format_%A"

报告“%A”未定义似乎是一种非常奇怪的行为,但它与这个问题没有直接关系,所以我打开了一个新的问题,为什么匹配的子字符串在JavaScript中返回“undefined”?。


问题是console.log像printf语句一样接受其参数,因为我记录的字符串(“%a”)有一个特殊值,所以它试图查找下一个参数的值。


当前回答

只有当你有一对括号时才实用的一行:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};

其他回答

如果你和我一样,希望正则表达式返回这样的Object:

{
    match: '...',
    matchAtIndex: 0,
    capturedGroups: [ '...', '...' ]
}

然后从下面剪切函数

/***@param{string | number}输入*要匹配的输入字符串*@param{regex | string}表达式*正则表达式*@param{string}标志*可选标志* *@return{array}* [{匹配:“…”,matchAtIndex:0,捕获的组:[“…”,“…”]}] */函数regexMatch(输入,表达式,标志=“g”){让regex=RegExp的表达式实例?表达式:新RegExp(表达式,标志)let matches=input.matchAll(正则表达式)匹配=[…匹配]return matches.map(项=>{返回{匹配:项[0],matchAtIndex:项索引,捕获组:item.length>1?item.s切片(1):未定义}})}let input=“key1:value1,key2:value2”让正则表达式=/(\w+):(\w+)/glet matches=regexMatch(输入,regex)console.log(匹配项)

只有当你有一对括号时才实用的一行:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
/*Regex function for extracting object from "window.location.search" string.
 */

var search = "?a=3&b=4&c=7"; // Example search string

var getSearchObj = function (searchString) {

    var match, key, value, obj = {};
    var pattern = /(\w+)=(\w+)/g;
    var search = searchString.substr(1); // Remove '?'

    while (match = pattern.exec(search)) {
        obj[match[0].split('=')[0]] = match[0].split('=')[1];
    }

    return obj;

};

console.log(getSearchObj(search));

这里有一个方法可以用来获得n​每个匹配的第个捕获组:

函数getMatches(字符串、正则表达式、索引){索引||(索引=1);//默认为第一个捕获组var matches=[];var匹配;while(match=regex.exec(字符串)){matches.push(match[index]);}返回匹配;}//示例:var myString=“something format_abc something format_def something form_ghi”;var myRegEx=/(?:^|\s)format_(.*?)(?:\s|$)/g;//获取包含每个匹配的第一个捕获组的数组var matches=getMatches(myString,myRegEx,1);//日志结果document.write(matches.length+'找到匹配项:'+JSON.stringify(匹配项))console.log(匹配项);

本回答中使用的术语:

Match表示对字符串运行RegEx模式的结果,例如:someString.Match(regexPattern)。匹配模式表示输入字符串的所有匹配部分,它们都位于匹配数组内。这些是输入字符串中模式的所有实例。匹配的组表示RegEx模式中定义的所有要捕获的组。(括号内的模式,如:/format_(.*?)/g,其中(.*!)将是匹配的组。)它们位于匹配的模式中。

描述

为了访问匹配的组,在每个匹配的模式中,您需要一个函数或类似的东西来迭代匹配。有很多方法可以做到这一点,正如许多其他答案所示。大多数其他答案使用while循环来遍历所有匹配的模式,但我认为我们都知道这种方法的潜在危险。需要匹配新的RegExp(),而不仅仅是模式本身,这只是在注释中提到的。这是因为.exec()方法的行为类似于生成器函数——它在每次匹配时都会停止,但在下一次.exec)调用时保持.lastIndex继续。

代码示例

下面是一个函数searchString的示例,它返回所有匹配模式的数组,其中每个匹配都是一个包含所有匹配组的数组。我没有使用while循环,而是提供了使用Array.prototype.map()函数的示例,以及一种更高效的方法——使用普通的for循环。

简洁的版本(更少的代码,更多的语法糖)

因为它们基本上实现了forEach循环,而不是更快的for循环,所以性能较差。

// Concise ES6/ES2015 syntax
const searchString = 
    (string, pattern) => 
        string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match => 
            new RegExp(pattern.source, pattern.flags)
            .exec(match));

// Or if you will, with ES5 syntax
function searchString(string, pattern) {
    return string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match =>
            new RegExp(pattern.source, pattern.flags)
            .exec(match));
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

Performant版本(更多代码,更少语法糖)

// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
    let result = [];

    const matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (let i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
};

// Same thing, but with ES5 syntax
function searchString(string, pattern) {
    var result = [];

    var matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (var i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

我还没有将这些替代方案与其他答案中提到的替代方案进行比较,但我怀疑这种方法的性能和故障安全性不如其他方法。