2009-05-09 14 views
60

Dlaczego pomniejszenie JavaScript przestaje działać po ustawieniu modyfikatora g?Wyrażenia regularne JavaScript i podfoldery

var text = 'test test test test'; 

var result = text.match(/t(e)(s)t/); 
// Result: ["test", "e", "s"] 

Powyższe działa dobrze, result[1] jest "e" i result[2] jest "s".

var result = text.match(/t(e)(s)t/g); 
// Result: ["test", "test", "test", "test"] 

Powyższe ignoruje moje grupy przechwytujące. Czy poniższe jedyne prawidłowe rozwiązanie?

var result = text.match(/test/g); 
for (var i in result) { 
    console.log(result[i].match(/t(e)(s)t/)); 
} 
/* Result: 
["test", "e", "s"] 
["test", "e", "s"] 
["test", "e", "s"] 
["test", "e", "s"] 
*/ 

Odpowiedz

91

Korzystanie String „s match() funkcja nie zwróci złapany grupy jeśli globalna modyfikator jest ustawiony, jak dowiedziałem.

W takim przypadku należy użyć obiektu RegExp i wywołać jego funkcję exec(). String ''s match() jest prawie identyczna z funkcją exec() ... z wyjątkiem takich przypadków. Jeśli modyfikator globalny jest ustawiony, normalna funkcja match() nie zwróci przechwyconych grup, a funkcja RegExp będzie miała wartość exec(). (Znany here, wśród innych miejscach).

Kolejny haczyk do zapamiętania jest to, że exec() nie zwraca mecze w jednym wielkim meczów array-Utrzymuje wracających dopóki nie skończy się w tym przypadku zwraca null.

Tak więc, na przykład, można zrobić coś takiego:

var pattern = /t(e)(s)t/g; // Alternatively, "new RegExp('t(e)(s)t', 'g');" 
var match;  

while (match = pattern.exec(text)) { 
    // Do something with the match (["test", "e", "s"]) here... 
} 

Inną rzeczą, aby pamiętać, że RegExp.prototype.exec() i RegExp.prototype.test() wykonać wyrażenie regularne na dostarczonych sznurka i zwróci pierwszy rezultat. Każde wywołanie sekwencyjne przechodzi przez zestaw wyników aktualizując RegExp.prototype.lastIndex w oparciu o bieżące położenie w łańcuchu.

Oto przykład: // pamiętaj, że w przykładzie i wzorze są 4 dopasowania. lastIndex zaczyna się od 0

pattern.test(text); // pattern.lastIndex = 4 
pattern.test(text); // pattern.lastIndex = 9 
pattern.exec(text); // pattern.lastIndex = 14 
pattern.exec(text); // pattern.lastIndex = 19 

// if we were to call pattern.exec(text) again it would return null and reset the pattern.lastIndex to 0 
while (var match = pattern.exec(text)) { 
    // never gets run because we already traversed the string 
    console.log(match); 
} 

pattern.test(text); // pattern.lastIndex = 4 
pattern.test(text); // pattern.lastIndex = 9 

// however we can reset the lastIndex and it will give us the ability to traverse the string from the start again or any specific position in the string 
pattern.lastIndex = 0; 

while (var match = pattern.exec(text)) { 
    // outputs all matches 
    console.log(match); 
} 

można znaleźć informacje na temat korzystania z obiektów on the MDNRegExp (w szczególności, tutaj jest dokumentacja dla the exec() function).

+3

za pomocą exec wydaje się nie słuchać modyfikatora g, ale obsługuje podprzedziały/grupy. Tak więc wynik byłby pierwszym dopasowaniem (w zasadzie ignoruje modyfikator g). –

+0

Dodano wyjaśnienie na ten temat - musisz wielokrotnie wywoływać exec(), aby uzyskać wiele dopasowań. – hbw

+2

Nie jest to najbardziej eleganckie rozwiązanie. i oczekiwał wyjście nieco tak: [ \t [ "test", "e", "e"], \t [ "test", "e", "e"], \t [” test "," e "," s "], \t [" test "," e "," s "] ] –

Powiązane problemy