Im trying to validate a username with RegEx in Javascript and while the result of .test
is true all works fine, but (somtimes) when i use a string that doesnt match, my app breaks and i get the error Too much recursion. I want to know where in my RegEx (Or code) have i gone wrong to cause such a thing.
This is my code (RegEx):
console.log(/^[A-Za-zÀ-ÖØ-öø-ÿ]([ _]?[A-Za-z0-9À-ÖØ-öø-ÿ] ) $/g.test("RegExr was created by gskinner_com_and is proudly hosted by Media Temple"));
I want the correct string to start with a letter, then have any combination of letters and digits with spaces and underscores allowed between them but only one at a time.
The regex works in websites related to testing it, and on my own code, and i get the error when the invalid input is far from the beginning of the string, in fact my computer takes longer to calculate the result the further i put the error (Lets say a dot or 2 spaces after each other) till on a certain point i get the error.
or the use of too many characters like
What is the problem? position of the $
or the use of too many characters like À-ÖØ-öø-ÿ
? and what can i do to fix it ?
CodePudding user response:
The catastrophic backtracking is due to the nested quantifiers in the group. If the pattern can not match, the nested quantifiers allow a lot of positions to backtrack to, still trying to get a match.
You could start the pattern matching a single char, and then optionally match one of the character class [A-Za-z0-9À-ÖØ-öø-ÿ]*
Then in the repeating group, match either a space or underscore [ _]
followed by 1 or more times the already existing character class [A-Za-z0-9À-ÖØ-öø-ÿ]
This does not disable the backtracking, it takes out a nested quantifier to allow for less positions to backtrack to.
Note that repeating a capture group, captures the value of the last iteration. If you don't need the capture group value afterwards, you can make it a non capture group using (?:
instead.
^[A-Za-zÀ-ÖØ-öø-ÿ][A-Za-z0-9À-ÖØ-öø-ÿ]*(?:[ _][A-Za-z0-9À-ÖØ-öø-ÿ] ) $
To also match a single word you can make the quantifier *
for the group to match zero or more times:
^[A-Za-zÀ-ÖØ-öø-ÿ][A-Za-z0-9À-ÖØ-öø-ÿ]*([ _][A-Za-z0-9À-ÖØ-öø-ÿ] )*$