Reputation: 1918
I think I've a problem with regular expression: I want a string wich can contains all the characthers in the first rounded parenthesis and eventually a [ and finally a ]. the regex is the following:
var pattern = /^(([a-zA-Z0-9\.\_\-\(\)\\'\xE0\xE8\xE9\xF9\xF2\xEC\x27\,\/]\s?)*\[?([a-zA-Z0-9\.\_\-\(\)\\'\xE0\xE8\xE9\xF9\xF2\xEC\x27\,\/]\s?)*\]?)+$/;
the problem is that if I try to test the following string Maionese [dfvdfv]@ my program will loop forever :-|
the function that I use to test is the following:
//the alert doesn't works
alert(checkSpecialIngredienti("Maionese [dfvdfv]@"));
function checkSpecialIngredienti(s) {
var pattern = /^(([a-zA-Z0-9\.\_\-\(\)\\'\xE0\xE8\xE9\xF9\xF2\xEC\x27\,\/]\s?)*\[?([a-zA-Z0-9\.\_\-\(\)\\'\xE0\xE8\xE9\xF9\xF2\xEC\x27\,\/]\s?)*\]?)+$/;
if (!pattern.test(s)) {
alert("Attenzione, il campo "+s+"" +
" che hai inserito non va bene!" +
"\nIn questo campo puoi inserire " +
"lettere, numeri, lettere accentate," +
"punteggiatura classica, singoli spazi e" +
"\nuna sola coppia di parentesi quadre." +
"\nRiprova!");
return (false);
} else
return true;
}
Upvotes: 2
Views: 762
Reputation: 336078
You're running into catastrophic backtracking because you have nested quantifiers (((...)*)+
), and the resulting combinatorial explosion will blow up your regex engine when the subject string cannot be matched.
Now, how to fix this? Let's first simplify your regex. There's a lot of irritating cruft in there - the following regex matches exactly the same strings as yours, but it's easier to read:
/^(([\w\s.,()\\\/'\xE0\xE8\xE9\xF9\xF2\xEC\x27-])*\[?([\w\s.,()\\\/'\xE0\xE8\xE9\xF9\xF2\xEC\x27-])*\]?)+$/
The problem now becomes clear: The []
s are both optional, and the @
in your test string is not part of the allowed character range. This means that upon encountering the @
, the regex engine needs to backtrack into the match and check if there is any other way to match the preceding part - and there are lots of ways that it has to try.
According to your specs, you don't need the final +
at all, since you seem to be wanting to match a string that contains any of the allowed characters plus one optional, [...]
-enclosed string of the same characters at the end. In that case, use
/^([\w\s.,()\\\/'\xE0\xE8\xE9\xF9\xF2\xEC\x27-]*)(\[[\w\s.,()\\\/'\xE0\xE8\xE9\xF9\xF2\xEC\x27-]*\])?$/
Upvotes: 2