2013-08-01 15 views
5

Próbuję usunąć problem z mojej aplikacji, który zawęziłem do konkretnej sytuacji, w której występuje wyrażenie regularne, które powoduje, że Chrome się dusi! Wypróbowanie tego samego kodu w Firefoksie działa dobrze. Również jeśli zredukuję tekst "próbki", aby uruchomić wyrażenie regularne, działa również.Dlaczego ten kod powoduje dezorientację Chrome?

Co daje?

Oto jsfiddle: http://jsfiddle.net/XWKRb/1/ (co nie można ich uruchomić w ogóle, ponieważ Chrome będzie dusić jeśli otrzymujesz ten sam wynik jak ja)

kod mam umieścić w jsfiddle jest:

var rgx = /^(\d+([,|;]?\d*))*$/; 
var sample = '40162690,40162755,40162691,40168355,40168357,40162726,40162752,40162729,40428707 ,40162740,40162546'; 
alert("Test is "+rgx.test(sample)); 

Być może istnieje lepszy sposób napisania mojego wyrażenia regularnego, aby uniknąć problemu? Celem jest wyrażenie regularne, które powinno złapać ciąg liczb oddzielonych przecinkiem lub średnikiem.

+0

Czy to przestrzeń w 'celowe kontrole wyrywkowe? –

+1

Mogę potwierdzić, że to łamie Google Chrome v28 na 64-bitowym Windows 7 –

+0

Ten błąd pojawia się tylko wtedy, gdy w ciągu próbki pojawia się spacja. –

Odpowiedz

13

masz klasyczny przypadek catastrophic backtracking:

^(\d+([,|;]?\d*))*$ 
    ^ ^^^
    |  | | ---- zero or more repetitions of the group 
    |  | ------- zero or more digits 
    |  ---------- zero or one comma, pipe or semicolon 
    ----------------- one or more digits 

zawiera powtarzające się grupy, która zawiera elementy opcjonalne, z których jeden znajduje się powtórzyła. Ignorując separatory do teraz, masz zasadniczo regex

^(\d+\d*)*$ 

która prowadzi do liczby wykładniczej permutacji Twój regex musi sprawdzić w najgorszym przypadku.

Gdy tylko znak znajdujący się poza dozwolonymi znakami zostanie znaleziony w twoim ciągu znaków (jak spacja w twoim przykładzie), wyrażenie regularne musi się nie powieść, ale zajmuje się wiekiem silnika, aby to zrozumieć. Niektóre przeglądarki wykrywają takie niekontrolowane dopasowania regex, ale wydaje się, że Chrome chce to wypróbować.

Aby to zilustrować, testując swój regex w RegexBuddy zawiera następujące informacje:

Input    Steps to determine a non-match 
1,1X     23 
12,21X    119 
123,321X    723 
1234,4321X   4,743 
12345,54321X  31,991 
123456,654321X 217,995 
1234567,7654321X attempt aborted after 1,000,000 steps 
+0

Powtarzająca się grupa zawiera nieobowiązkowy element '\ d +'. –

+0

@LightnessRacesinOrbit: Masz rację; problem jest jednak nadal ten sam. –

+1

dzięki za wyjaśnienie tego problemu! – Trant

4

Ten wzór będzie działać lepiej:

var rgx = /^\d+(?:[,;]\s*\d+)*$/; 
+0

Nie akceptuje jednak pustego ciągu znaków .. nie jestem pewien, czy było to ważne w oryginalnym – Esailija

+0

Tak, to wyrażenie wykonuje to zadanie, nie powodując tej samej nieskończonej pętli - dzięki! – Trant

+0

@Trant: różni się od nieskończonej pętli i jest raczej zbyt dużą możliwością wypróbowania. –

Powiązane problemy