views:

118

answers:

3

I have the following regex pattern: (.NET 1.1 Regex Validator)

^(?=.*[A-Za-z])[a-zA-Z0-9@\\-_\\+\\.]{6,32}$

I need to meet the following requirements:

6 to 32 characters must contain at least one letter. Allowed characters are letters (a-z, A-Z), numbers (0-9), @ ("at" symbol), . (period), _ (underscore), + (plus), - (minus).

Any entries starting with numeric values, seem to be 'skipped' until non numeric values are encountered.

123abc fails
123abcde fails
123abcdef passes

So I see that it's 'counting' the look ahead AFTER the numeric values, why?

Thanks.

A: 

It's counting the lookahead after the digits because you allowed as much with

(?=.*[A-Za-z])

The .* means "after zero or more characters."

If you want to force a letter at the beginning, modify your pattern:

^[A-Za-z][-a-zA-Z0-9@_+.]{5,31}$
Greg Bacon
So how do I fix that?
John Batdorf
`(?= )` is a **zero width** positive lookahead assertion, so the "cursor" is being reset after the check.
Richard Szalay
He doesn't want to assert a letter at the start, only that the string *contains* a letter.
Richard Szalay
That is correct Richard, thanks.
John Batdorf
No probs! How'd the regex from my answer fair?
Richard Szalay
Then we're missing a piece of the puzzle somewhere. The example strings you gave all match the pattern from your question. Do your program's actual inputs, for example, contain more than than the 6- to 32-character fields?
Greg Bacon
But they don't match. Try it in .NET 1.1 in IE.
John Batdorf
Richard it didn't work.
John Batdorf
+2  A: 

It's quite possible that it's a bug in .NET 1.1. All of your "fail" examples work using Regex Hero, which is based on Silverlight which uses the .NET 2.0 Regex implementation.

You might try using a positive look-behind assertion instead and see if that gets around the problem:

^[a-zA-Z0-9@\-_\+\.]{6,32}(?<=.*[A-Za-z])$

Edit: Considering this is an ASP.NET validator, you should double check that it's not failing client validation (javascript). Some advanced features (like zero-width look ahead/behinds) are not supported by some browsers.

Try to disable client side validation by setting EnableClientScript to false on the RegularExpressionValidator and see if that fixes the problem. If it does, then it's a browser support issue and I'd recommend splitting your validation into two:

  1. ^[a-zA-Z0-9@\-_\+\.]{6,32}$ # must be 6-32 characters
  2. ^.*[A-Za-z].*$ # must contain a letter
Richard Szalay
Does .NET support variable-width lookbehinds?
Anon.
I don't believe so, though I'm not familiar with the concept.
Richard Szalay
Yes, .NET regexes support unknown-width lookbehinds. At least, they do in .NET 3.5; whether they did in .NET 1.1, and whether it worked correctly, I couldn't say.
Alan Moore
I see what you mean now (they are referred to as zero-width lookbehinds in .NET), and yes they are supported.
Richard Szalay
Actually, "zero-width" merely refers to the fact that they don't consume any characters; lookaheads, lookbehinds, word boundaries (`\b`) and anchors (`^`, `$`, `\A`, `\Z`, `\z`) are all zero-width assertions. "Unknown-width" was my ill-advised attempt to abbreviate "able to match a variable number of characters, with no restrictions". Java and PHP (PCRE) lookbehinds aren't limited to fixed-width matches like most other flavors', but they aren't completely unrestricted like .NET's lookbehinds either.
Alan Moore
That's a good suggestion about the client-side validation. JavaScript regexes do support lookaheads (which is all the OP is using), but that support is notoriously inconsistent among the myriad browsers/versions. And if your dual-validator idea doesn't work, it's time to get out the sledgehammer. :P
Alan Moore
+1  A: 

Have you tried refactoring the regex? For example:

^(?=[a-zA-Z0-9_@+.-]{6,32}$).*[A-Za-z].*$

Or just "pad" your lookahead so it has to match all the way to the end:

^(?=.*[A-Za-z].*$)[a-zA-Z0-9_@+.-]{6,32}$

Maybe that will reset the match position so the second part can start matching at the beginning. It shouldn't be necessary, of course, but I can't see any reason why your regex wouldn't work as written.

Alan Moore