Regex fails only on Safari - javascript

I have the following simple email validation regex: /(.+){2,}#(.+){2,}\.(.+){2,}/
This works fine on Firefox, Chrome etc, but fails on Safari.
Why would this perfectly valid regex fail on Safari? I could not find elements in the regex that are not supported by Safari.
/(.+){2,}#(.+){2,}\.(.+){2,}/.test('123#abc.nl');
Above fails on Safari, but not on any other browser.

Different regex engines have different tolerance to catastrophic backtracking prone patterns.
Yours is a catastrophic backtracking prone pattern as you quantify (.+) with the {2,} quantifier that makes (.+) match two or more times (that is, match one or more times twice or more, which makes it fail very slowly with non-matching patterns.)
If you meant to match any two or more chars, quantify the . pattern and not a .+ one:
/.{2,}#.{2,}\..{2,}/
Or, use existing email validation patterns..

Related

REGEX working in chrome but breaks in safari

The following javascript regex breaks in safari getting SyntaxError: Invalid regular expression: invalid group specifier name"
/^(?!\s)[A-Za-z0-9\'\.\-\,\s]*(?<!\s)$/.test('ABCD##');
Can someone please help me to re write the regex which can work in safari?
I find out that safari doesn't support lookbehind but still not able to re write the whole regex which can be good for safari.
Modify your pattern to avoid the negative lookbehind. Since you seem to want a non whitespace character as the last character, just use a character class for that.
/^(?!\s)[A-Za-z0-9'.,\s-]*[A-Za-z0-9'.,-]$/.test('ABCD##')
Side note: your current pattern looks wrong for what you are trying to match.

Regex Pattern Causes Catastrophic Backtracking In Edge Cases

I have these two simple regex patterns to match urls that are from these stores, but they lead to catastrophic backtracking and a frozen browser when running on some string url with an edge case. This logic is running on thousands of random requests, so the chance of catastrophic backtracking is high. Does anyone have an idea of what could be wrong in the way I wrote this regex.
> ".*://.*.newegg.com/Product/Product.*"
> ".*://.*.gamestop.com*.*Product-Variation*.*productDetailsRedesign"
You have too many greedy dot patterns in the expressions. Try be a ted bit more verbose:
\w+://[^/]*\.newegg\.com/Product/Product\S*
The second pattern:
\w+://[^\s/]*\.gamestop\.com\S*?Product-Variation\S*?productDetailsRedesign
See proof #1 | proof #2.
Use \S*? to match any characters different from whitespace (as few as possible).
Escape the period characters as they are regex metacharacters.
Use [^...] negated character classes if you know there can be no such characters between two substrings in a match.

Regex - Validate that the local part of the email is not ending with a dot while only allowing certain characters without using a lookbehind

I was using a lookbehind to check for a dot before the # but just realized not all browsers are supporting lookbehinds. It works perfect in Chrome but fails in Firefox and IE.
This is what I came up with but it certainly is messy
^([a-zA-Z0-9&^*%#~{}=+?`_-]\.?)*[a-zA-Z0-9&^*%#~{}=+?`_-]#([a-zA-Z0-9]+\.)+[a-zA-Z]$
Is there a simpler and/or more elegant way to do this? I don't think I can negate the dot (^.) because I'm only allowing certain characters to be present in the local part.
This ([a-zA-Z0-9&^*%#~{}=+?`_-].?)*[a-zA-Z0-9&^*%#~{}=+?`_-] part is not messy, but inefficient, because the * quantifies a group containing an obligatory part, [...], and an optional \.?. Instead of (ab?)*a, you may use a+(?:ba+)* that will make matching linear and swift, in your case, [a-zA-Z0-9&^*%#~{}=+?`_-]+(?:.[a-zA-Z0-9&^*%#~{}=+?`_-]+)*.
More, [a-zA-Z0-9_] equals \w in JS regex, you may use this to shorten the pattern.
Besides, the last [a-zA-Z]$ pattern only matches a single letter, you most probably need [a-zA-Z]{2}$ there, as TLDs consist of 2+ letters.
So, you may use
^[\w&^*%#~{}=+?`-]+(?:\.[\w&^*%#~{}=+?`-]+)*#(?:[a-zA-Z0-9]+\.)+[a-zA-Z]{2,}$
See the regex demo.

Regex error in Netbeans not present in other editors

I have the following regular expression that works fine in my application code and other code editors have not reported a problem with it. It is used to validate a password.
/^(?=.*[A-Za-z])+(?=.*[\d])+(?=.*[^A-Za-z\d\s])+.*$/
So in other words:
Must have one letter
Must have one digit
Must have one non-letter, non-digit
Now it seems netbeans has a fairly decent regex parser and it has reported that this is an erroneous statement. But as i am new to regex I cannot spot the error. Is it due to using the positive lookahead ?= with the one or more + at the end?
When I take out the + the error goes away, but the regex stops performing in my application.
If anyone can tell me what is wrong with my expression that would be great.
The statement is used in a jQuery validation plugin that i use, if that helps. Also due to the fact I am using a plugin, I would prefer not splitting this into several smaller (clearly simpler and cleaner) expressions. That would require a great deal of work.
It never makes sense to apply a quantifier to a zero-width assertion such as a lookahead. The whole point of such assertions is that they allow you to assert that some condition is true, without consuming any of the text--that is, advancing the current match position. Some regex flavors treat that as a syntax error, while others effectively ignore the quantifier. Getting rid of those plus signs makes your regex correct:
/^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z\d\s]).*$/
If it doesn't work as expected, you may be running into the infamous IE lookahead bug. The usual workaround is to reorder things so the first lookahead is anchored at the end, like so:
/^(?=.{8,15}$)(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z\d\s]).*/
The (?=.{8,15}$) is just an example; I have no idea what your real requirements are. If you do want to impose minimum and maximum length limits, this is the ideal place to do it.

help making a "universal" regex Javascript compatible

I found a very nice URL regex matcher on this site: http://daringfireball.net/2010/07/improved_regex_for_matching_urls . It states that it's free to use and that it's cross language compatible (including Javascript). First of all, I have to escape some of the slashes to get it to compile at all. When I do that, it works fine on Rubular.com (where I generally test regexes), with the strange side effect that each match has 5 fields: 1 is the url, and the extra 4 are empty. When I put this in JS, I get the error "Invalid Group". I am using Node.js if that makes any difference, but I wish I could understand that error. I'd like to cut back on the unnecessary empty match fields, but I don't even know where to begin diagnosing this beast. This is what I had after escaping:
(?xi)\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’] ))
Actually, you don't need the first capturing group either; it's the same as the whole match in this case, and that can always be accessed via $&. You can change all the capturing groups to non-capturing by adding ?: after the opening parens:
/\b(?:(?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\((?:[^\s()<>]+|(\(?:[^\s()<>]+\)))*\))+(?:\((?:[^\s()<>]+|(?:\(?:[^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i
That "invalid group" error is due to the inline modifiers (i.e., (?xi)) which, as #kirilloid observed, are not supported in JavaScript. Jon Gruber (the regex's author) was mistaken about that, as he was about JS supporting free-spacing mode.
Just FYI, the reason you had to escape the slashes is because you were using regex-literal notation, the most common form of which uses the forward-slash as the regex delimiter. In other words, it's the language (Ruby or JavaScript) that requires you to escape that particular character, not the regex. Some languages let you choose different regex delimiters, while others don't support regex literals at all.
But these are all language issues, not regex issues; the regex itself appears to work as advertised.
Seemes, that you copied it wrong.
http://www.regular-expressions.info/javascript.html
No mode modifiers to set matching options within the regular expression.
No regular expression comments
I.e. (?xi) at the beginning is useless.
x is useless at all for compacted RegExp
i can be replaced with flag
All these result in:
/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i
Tested and working in Google Chrome => should work in Node.js

Categories

Resources