1

I have the following regex:

^(?:[\w]+?\/)?[\w]+?@[\w]+?\.[\w]+?$

Now I need to limit the overall string length by 25 characters: I tried the following:

^((?:[\w]+?\/)?[\w]+?@[\w]+?\.[\w]+?){0,25}$

But it still matches regexes over 25 characters, why?

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • Can you post some examples which is matched or not? – Tim007 Mar 03 '16 at 11:12
  • 7
    that matches 0 to 25 occurrences of what's in the outer () – Jaromanda X Mar 03 '16 at 11:13
  • 1
    why can't you simply check if the length of string is less than or equal to 25? – gurvinder372 Mar 03 '16 at 11:13
  • This type of questions starts being asked every day. See [my recent answer](http://stackoverflow.com/questions/32477182/restricting-character-length-in-regular-expression). I marked as a dupe because I believe my answer in the original question contains the explanation how restricting with a lookahead works in the regex. – Wiktor Stribiżew Mar 03 '16 at 11:22
  • @WiktorStribiżew, yeah, ok, but the bit I was misunderstanding was that the token meant _the string in the regexp can be repeated n times_, not how positive lookahead works. Please add this to your answer if this bit is missing as it's crucial. Thanks! – Max Koretskyi Mar 03 '16 at 11:24
  • I see, I will add a bit more details there. The quantifiers only quantify the pattern they are applied to and when there are several ones with `+` or `*` quantifiers, you just cannot rely on setting the limiting quantifier to any one of them, or even enclosing all of them with a grouping construct and setting the limiting quantifier on it (as it will quantify unlimited number of times even more!) – Wiktor Stribiżew Mar 03 '16 at 11:26
  • I added *Why not use a limiting quantifier, like `{1,15}`, at the end?* section to my answer in the [*Restricting Character length in Regular expression*](http://stackoverflow.com/questions/32477182/restricting-character-length-in-regular-expression). – Wiktor Stribiżew Mar 03 '16 at 11:34
  • @WiktorStribiżew, great, thanks a lot, that's very helpful. One more question though, are the following tokens equal `\w{0,}` and `\w*` ? And I also didn't understand why Tim Pietzcker dropped lazy quantifiers, can you add anything about that? – Max Koretskyi Mar 03 '16 at 11:36
  • I added about lazy quantifiers. In your case, there is no difference, they are just working as greedy ones. So no need making your pattern longer than it needs. `\w{0,}` = `\w*`. – Wiktor Stribiżew Mar 03 '16 at 11:40

3 Answers3

4

A quantifier is applied to the token preceding it. In your case, that's an entire group, and that group can match much more than a single character.

Do the length check separately, using a positive lookahead assertion:

^(?=.{0,25}$)(?:\w+\/)?\w+@\w+\.\w+$

As you can see, your regex can also be simplified quite a bit (no need for lazy quantifiers and character classes).

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • thanks, I now understand the problem. I made quantifier `{2}` and duplicated the string and so it matched, and I see what you mean. One question, why did you drop lazy quantifiers? – Max Koretskyi Mar 03 '16 at 11:21
  • You do not need lazy quantifiers when you actually need greedy ones. – Wiktor Stribiżew Mar 03 '16 at 11:23
  • @WiktorStribiżew, thanks, but I don't understand why I need greed ones here. Can you elaborate? – Max Koretskyi Mar 03 '16 at 11:25
  • 2
    When you know you need to match all alphanumeric symbols and then a `.`, there is no need using `\w+?\.` as `\w+\.` will work the same. We need lazy quantifiers when some pattern may match the same type of characters as the subsequent pattern, but we want to stop at the first occurrence of that character. It is a good idea to avoid lazy matching when your pattern is known (like in your case). – Wiktor Stribiżew Mar 03 '16 at 11:37
  • @WiktorStribiżew, got it, thanks a lot for your very helpful feedback :) – Max Koretskyi Mar 03 '16 at 11:44
2

why not simply

if ( inputStr.length <= 25 && /^(?:[\w]+?\/)?[\w]+?@[\w]+?\.[\w]+?$/.test( inputStr ) )
{
  //your logic
}
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
1

If we call your original regex A

^(?:[\w]+?\/)?[\w]+?@[\w]+?\.[\w]+?$

Then your next regex can be expressed more simply as

^(A){0,25}$

So you're not matching only 25 characters, you're matching A 0 to 25 times

Gareth Parker
  • 5,012
  • 2
  • 18
  • 42