2011-06-17 181 views
3

我經常想用正則表達式解析字符串,並找到所有匹配項加上所有不匹配的字符串,並且所有匹配的字符串都以它們的原始順序散佈,例如從JavaScript正則表達式中獲取匹配數組和簡單字符串

var parsed = regexParse(/{([^}]+)}/g, 'Hello {name}, you are {age} years old'); 

所以parsed將包含:

0 : "Hello " 
1 : match containing {name}, name 
2 : ", you are " 
3 : match containing {age}, age 
4 : " years old" 

是否有任何的JavaScript(或一些廣泛使用的庫),類似於此regexParse功能?我寫我自己的版本,但它似乎太明顯了,我懷疑是不是必須已經有這樣做的一個「標準」的方式:

var regexParse = function(rx, str) { 
    var nextPlain = 0, result = [], match; 
    rx.lastIndex = 0; 
    for (;;) { 
    match = rx.exec(str); 
    if (!match) { 
     result.push(str.substr(nextPlain)); 
     break; 
    } 
    result.push(str.substr(nextPlain, match.index - nextPlain)); 
    nextPlain = rx.lastIndex; 
    result.push(match); 
    } 
    return result; 
}; 

更新

關於丹尼斯的回答,起初我以爲它會失敗,因爲返回數組中的所有值都是字符串。你怎麼知道哪些項目是不匹配的文本,哪些來自比賽?

但實驗位(與IE9和Chrome反正)表明,當split以這種方式使用時,它總是交替的片,以使得首先是從純文本,所述第二匹配,第三個是純文本等等。即使有兩個沒有匹配不匹配文本的匹配,它也遵循這個規則 - 在這種情況下,它輸出一個空字符串。

即使在簡單的情況:

'{x}'.split(/{([^}]+)}/g) 

輸出是嚴格:

["", "x", ""] 

所以,你可以告訴哪個是哪個,如果你知道如何(如果這個假設成立)!

我喜歡使用ES5 array methodsmap,forEachfilter。所以用我的原始regexParse這是一個使用typeof i == 'string來檢測哪些項目是不匹配的文本的問題。

隨着split它必須從返回數組中的位置決定的,不過沒關係,因爲ES5陣列方法傳遞第二個參數,指標,所以我們只需要看看它的奇(匹配)甚至(無與倫比的文字)。因此,例如,如果我們有:

var ar = '{greeting} {name}, you are {age} years old'.split(/{([^}]+)}/g); 

現在ar包含:

["", "greeting", " ", "name", ", you are ", "age", " years old"] 

從我們能夠得到公正的比賽:

ar.filter(function(s, i) { return i % 2 != 0; }); 

>>> ["greeting", "name", "age"] 

或者只是純文本,剝出空字符串還有:

ar.filter(function(s, i) { return (i % 2 == 0) && s; }); 

>>> [" ", ", you are ", " years old"] 
+1

+1也許不是問題究竟,但要求將導致這樣一個夢幻般回答的問題。對此非常興奮。 – Ben 2013-08-22 00:41:38

回答

6

我認爲你正在尋找split()與捕獲括號:

var myString = "Hello 1 word. Sentence number 2."; 
var splits = myString.split(/(\d)/); // Hello ,1, word. Sentence number ,2, . 
+0

真棒,我從來沒有聽到或看到與分裂之前捕獲parens,這是非常有用的 – qwertymk 2011-06-17 12:25:05