2012-06-04 45 views
14

究竟是什么标题要求。我会在解释我的问题时提供一些示例。在数组中存储JS Regex捕获组的最佳方法?

测试字符串:

var test = "#foo# #foo# bar #foo#"; 

说,我想提取#(所有foo秒,但不bar)之间的所有文本。

var matches = test.match(/#(.*?)#/g); 

使用.match如上所述,它会储存所有的比赛,但它会简单地扔掉捕获组看来。

var matches2 = /#(.*?)#/g.exec(test); 

.exec方法显然在位置1位置阵列的0且匹配的我的唯一的捕获组只返回该第一结果的匹配的字符串。

我已经穷尽了,谷歌和MDN寻找一个无济于事的答案。

所以,我的问题是,有没有更好的方式来存储匹配的捕获组,而不是通过循环遍历它与.exec和调用array.push来存储捕获的组?

我对上面的测试预期阵列应该是:

[0] => (string) foo 
[1] => (string) foo 
[2] => (string) foo 

纯JS和jQuery的答案被接受,额外的饼干,如果你发布的jsfiddle与console.log。 =]

回答

14

您可以使用.exec太像下面建立一个数组从Here

那么找到

var arr = [], 
    s = "#foo# #bar# #test#", 
    re = /#(.*?)#/g, 
    item; 

while (item = re.exec(s)) 
    arr.push(item[1]); 

alert(arr.join(' '));​ 

Working Fiddle

,它仍然有一个循环,如果你不想一个循环,然后我认为你必须去与.replace()。在这种情况下,代码就会像

var arr = []; 
var str = "#foo# #bar# #test#" 
str.replace(/#(.*?)#/g, function(s, match) { 
          arr.push(match); 
         }); 

检查从MDN DOC这些线,说明你有关查询如何exec更新lastIndex财产我想,

如果你的正则表达式使用“G”标志,您可以多次使用exec 方法在同一个字符串中查找连续的匹配项。

当你这样做的时候,搜索开始于 正则表达式的lastIndex属性指定的str的子字符串(test也会提前 lastIndex属性)。

+0

与我发现的'.exec'循环类似,但更简单和优雅,看起来像是一个合适的答案,因为我可以访问所有匹配并从'item'数组中捕获组。 –

+0

如果你想看到更多的JS魔法,你可以检查[我不是我]的答案(http://stackoverflow.com/users/1106925/am-not-i-am),它来自其中一个他的回答。 :) –

+0

已收藏他的个人资料以便稍后阅读答案=]现在,即使在阅读[MDN文档](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp/exec)之后, t找到'.exec'每次调用时都知道从哪里开始匹配字符串(“offset”?),好的重要的是它的工作原理。我认为它会自动存储'lastIndex'属性?如果任何人都可以发表评论,请做。 =] –

4

我不知道如果这是你正在寻找的答案,但您可以尝试下面的代码:

var matches = []; 
 

 
var test = "#foo# #foo# bar #foo#"; 
 

 
test.replace(/#(.*?)#/g, function (string, match) { 
 
    matches.push(match); 
 
}); 
 

 
alert(JSON.stringify(matches));

希望它能帮助。

+0

使用'.replace'来利用全局修饰符,这是一个非常好用的技巧(比用'.exec'这个问题循环更好)。如果没有更好的选择,我现在就会为它+1,并在睡觉前接受(让这个问题稍后打开,因为它可能对未来的参考有用)。 =] –

0

另一个想法,虽然执行效率很高。

var s= "#foo# #foo# bar #foo#"; 
s= s.match(/#([^#])*#/g).join('#').replace(/^#+|#+$/g, '').split(/#+/); 
2

data.replace(/.*?#(.*?#)/g, '$1').split(/#/)
没有循环,没有任何功能。

+0

另外,错误的输出。预期'[“foo”,“foo”,“foo”]'。实际的'[“foo”,“foo”,“foo”,“”]'。 –

+0

@AaditMShah是的,这是一个缺点 - 你总是不得不弹出额外的。发现得好。 – Leonid

0

如果有人到我的类似需要,我需要一个Django风格的URL配置处理程序的匹配函数,可以将路径“参数”传递给控制器​​。我想出了这个。当然,如果匹配'$',它不会工作得很好,但不会因'1.00美元'而中断。这比需要更明确一点。你可以从else语句中返回matchedGroups,而不用为for循环测试打扰,但;;;在循环声明的中间,有时候会让人不知所措。

var url = 'http://www.somesite.com/calendar/2014/june/6/'; 
var calendarMatch = /^http\:\/\/[^\/]*\/calendar\/(\d*)\/(\w*)\/(\d{1,2})\/$/; 

function getMatches(str, matcher){ 
    var matchedGroups = []; 
    for(var i=1,groupFail=false;groupFail===false;i++){ 
     var group = str.replace(matcher,'$'+i); 

     groupFailTester = new RegExp('^\\$'+i+'$'); 

     if(!groupFailTester.test(group)){ 
      matchedGroups.push(group); 
     } 
     else { 
      groupFail = true; 
     } 
    } 
    return matchedGroups; 
} 

console.log(getMatches(url, calendarMatch)); 
相关问题