如何访问JavaScript正则expression式中的匹配组?
我想用一个正则expression式来匹配string的一部分,然后访问那个被括起来的子string:
var myString = "something format_abc"; // I want "abc" var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString); console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good. console.log(arr[1]); // Prints: undefined (???) console.log(arr[0]); // Prints: format_undefined (!!!)
我究竟做错了什么?
我发现上面的正则expression式代码没有错:我testing的实际string是这样的:
"date format_%A"
报告“%A”未定义似乎是一个非常奇怪的行为,但它不是直接关系到这个问题,所以我打开了一个新的, 为什么匹配的子string在JavaScript中返回“undefined”? 。
问题是, console.log
的参数就像一个printf
语句,由于我logging的string( "%A"
)有一个特殊的值,它试图find下一个参数的值。
您可以像这样访问捕获组:
var myString = "something format_abc"; var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g; var match = myRegexp.exec(myString); console.log(match[1]); // abc
这里有一个方法可以用来获得每个匹配的第n个捕获组:
function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = 'something format_abc something format_def something format_ghi'; var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + ' matches found: ' + JSON.stringify(matches)) console.log(matches);
var myString = "something format_abc"; var arr = myString.match(/\bformat_(.*?)\b/); console.log(arr[0] + " " + arr[1]);
你的语法可能不是最好的。 FF / Gecko将RegExp定义为Function的扩展。
(FF2走到了typeof(/pattern/) == 'function'
)
看来这是特定于FF – IE,Opera和Chrome都会抛出exception。
而是使用前面提到的其他方法: RegExp#exec
或String#match
。
他们提供了相同的结果:
var regex = /(?:^|\s)format_(.*?)(?:\s|$)/; var input = "something format_abc"; regex(input); //=> [" format_abc", "abc"] regex.exec(input); //=> [" format_abc", "abc"] input.match(regex); //=> [" format_abc", "abc"]
关于上面的多重匹配括号的例子,在我没有得到我想要的东西之后,我在这里寻找答案:
var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);
用上面的while和.push()函数调用稍微复杂的函数后,发现问题可以用mystring.replace()很好地解决(replace不是重点,甚至没有完成,CLEAN,第二个参数的内置recursion函数调用选项是!):
var yourstring = 'something format_abc something format_def something format_ghi'; var matches = []; yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );
在这之后,我不认为我会永远不会再使用.match()。
最后但并非最不重要的是,我发现一行代码适用于我(JS ES6):
var reg = /#([\S]+)/igm; //get hashtags var string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris'; var matches = string.match(reg).map(e => e.replace(reg, '$1')); console.log(matches);
只有在有一对括号的情况下才有实际意义:
while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
使用你的代码:
console.log(arr[1]); // prints: abc console.log(arr[0]); // prints: format_abc
编辑:Safari 3,如果它很重要。
你的代码适用于我(Mac上的FF3),即使我同意PhiLo的正则expression式可能应该是:
/\bformat_(.*?)\b/
(但是,当然,我不确定,因为我不知道正则expression式的上下文。)
function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)'; var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + ' matches found: ' + JSON.stringify(matches)) console.log(matches);
没有必要调用exec
方法! 您可以直接在string上使用“匹配”方法。 只是不要忘记括号。
var str = "This is cool"; var matches = str.match(/(This is)( cool)$/); console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...
位置0包含所有结果的string。 位置1的第一个匹配用圆括号表示,位置2的第二个匹配用圆括号括起来。 嵌套括号是棘手的,所以要小心!
在这个答案中使用的术语:
- Match表示对您的string运行RegEx模式的结果,如下所示:
someString.match(regexPattern)
。 - 匹配模式表示inputstring的所有匹配部分,它们全部驻留在匹配数组中。 这些都是你的模式在inputstring中的所有实例。
- 匹配的组指示要在RegEx模式中定义的所有要捕获的组。 (括号内的模式,如下所示:/
/format_(.*?)/g
(.*?)
//format_(.*?)/g
,其中(.*?)
将是匹配的组)。这些位于匹配的模式中 。
描述
要访问匹配的组 ,在每个匹配模式中 ,需要一个函数或类似的东西来遍历匹配 。 有很多方法可以做到这一点,就像许多其他的答案一样。 大多数其他答案使用while循环遍历所有匹配的模式 ,但我认为我们都知道这种方法的潜在危险。 有必要匹配一个new RegExp()
而不是模式本身,只有在评论中提到。 这是因为.exec()
方法的行为类似于生成器函数 – 每次匹配时都会停止 ,但在下一个.exec()
调用时保持它的.lastIndex
继续。
代码示例
下面是一个函数searchString
的例子,它返回一个所有匹配模式的Array
,每个match
是一个包含所有包含匹配组的Array
。 我没有使用while循环,而是使用Array.prototype.map()
函数以及更高性能的方式提供了示例 – 使用plain for
-loop。
简洁的版本(更less的代码,更多的语法糖)
这些性能较差,因为它们基本上实现了for
loop而不是更快的for
-loop。
// 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
高性能版本(更多的代码,更less的语法糖)
// 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
我还没有将这些替代scheme与其他答案中提到的替代方法进行比较,但是我怀疑这种方法的性能不如其他方法高。
/*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));
看看第12课的这个链接 :
您可以使用特殊
(
和)
(括号)对字符进行分组。 要捕获图像文件,请写下expression式^(IMG(\d+))\.png$
。