2

I have a working regex pattern in C# .NET which works great as expected. I just want to update this pattern to make sure any string that is compared with this regex is not start with any special Characters.

My Existsing Regex

(@"^(?=.*[A-Z])(?=.*[!\{\}\[\]@#$%^&*()+_<>~-])(?=.*[0-9])(?=.*[a-z]).{8,15}$");

For Example

TestHey@123! - Pass

@TestHey123! - This should fail because special character at the beginning.

sgl
  • 563
  • 1
  • 6
  • 16
  • 3
    What, _exactly_, do you define as a "special character"? – gunr2171 Apr 26 '23 at 17:10
  • Can you tell us a bit about your existing format? Why do you use so many lookaheads? Does this need to be a modification to your existing regex pattern, or can you run multiple regex/string checks to accomplish this goal? – gunr2171 Apr 26 '23 at 17:22
  • Here is my current error message as per current patter – sgl Apr 26 '23 at 17:52
  • Password must be minimum 8 characters and maximum 15 characters in length.
    Password must contain atleast 1 Uppercase character1 Lowercase character1 Numerical digit and
    1 Special character like ~!@$%^&*()_+-<>[]{}
    – sgl Apr 26 '23 at 17:52
  • these are my special characters: ~!@$%^&*()_+-<>[]{} – sgl Apr 26 '23 at 17:52
  • 1
    I wouldn't use _one_ regex to check a password's requirements. Split out your requirements into their own logic, similar to https://stackoverflow.com/a/40910204/1043380 – gunr2171 Apr 26 '23 at 17:58
  • Regexs are very powerful, but the regex shown in your question is very hard to understand. Complex regexs are hard to maintain and hard to understand; as indicated by your question. Adding extra checks into it will make it even more complex and even harder to maintain in the future. I suggest using several smaller regexs and some C# code to select when to apply them. – AdrianHHH Apr 26 '23 at 20:20

2 Answers2

1

You can do it by simply specifying character class for first symbol of password separately from next seven to fifteen symbols:

^(?=.*[A-Z])(?=.*[!\{\}\[\]@#$%^&*()+_<>~-])(?=.*[0-9])(?=.*[a-z])[^!\{\}\[\]@#$%^&*()+_<>~-].{7,14}$

This will exclude specifically listed symbols. But other symbols like ё will be allowed.

If you want one of Latin letters or digits, you can specify this in the following way:

^(?=.*[A-Z])(?=.*[!\{\}\[\]@#$%^&*()+_<>~-])(?=.*[0-9])(?=.*[a-z])[a-zA-Z0-9].{7,14}$

Demo here.

markalex
  • 8,623
  • 2
  • 7
  • 32
1

An idea to use a \b word boundary at start to force a word character but exclude the underscore. The advantage is, that if applicable the regex will fail right away before triggering the lookaheads. Further I recommend to use negation before the required character in the lookaheads (efficiency).

^\b(?!_)                         # start with a word character excluding underscore
(?=\D*\d)                        # look ahead for a digit preceded by any non-digits
(?=[^A-Z]*[A-Z])                 # look ahead for an upper preceded by any non-upper
(?=[^a-z]*[a-z])                 # look ahead for a lower preceded by any non-lower
(?=.*[!{}\[\]@\#$%^&*()<>_~+\-]) # one special character preceded by any characters
.{8,15}$                         # 8 to 15 characters until the end

See this demo at regex101 (\n in the demo is just added for multiline testing) - Regex in one line:

^\b(?!_)(?=\D*\d)(?=[^A-Z]*[A-Z])(?=[^a-z]*[a-z])(?=.*[!{}\[\]@\#$%^&*()<>_~+\-]).{8,15}$
bobble bubble
  • 16,888
  • 3
  • 27
  • 46