2012-06-04 48 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)); 
相關問題