Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex: Optional special characters

Tags:

regex

I have a regex which has the following rules:

+ Must contain lower case letters
+ Must contain upper case letters
+ Must contain a number
+ Must contain a (defined)special character
+ At least 8 chars

This works and my regex looks like this:

((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[~@#\$%\^&\*_\-\+=`|{}:;!\.\?\"()\[\]]).{8,25})

Now I want to change that regex in only one single thing: The special characters should still be possible (and only those I allow), but should be optional (not required anymore) anywhere in the string. So the new rule would be

+ MAY contain (defined) special characters

What do I have to change to achieve this?

Examples:

NicePassw0rd - NOT OK now, should be
NicePassw0rd%% - OK now (and still should be)
NicePassword - NOT OK now and shouldnt

You can test my regex there: https://regex101.com/r/qN5dN0/1

like image 899
Ole Albers Avatar asked Dec 19 '22 22:12

Ole Albers


1 Answers

You must add anchors ^ and $ on both ends of the pattern to really enable length checking. If you want to disallow other special characters, move ~@#$%^&*+=`|{}:;!.?\"()\[\]- to the consuming part with letters and digits (note that [A-Za-z0-9_] is the same as \w if you are using PCRE without /u flag):

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[\w~@#$%^&*+=`|{}:;!.?\"()\[\]-]{8,25}$

See regex demo

Here is what it does:

  • ^ - start of string
  • (?=.*\d) - require at least one digit
  • (?=.*[a-z]) - require at least a lowercase ASCII letter
  • (?=.*[A-Z]) - require at least 1 ASCII uppercase letter
  • [\w~@#$%^&*+=`|{}:;!.?\"()\[\]-]{8,25} - match (=consume) 8 to 25 only symbols that are either alphanumeric, or _, or all those inside the character class
  • $ - end of string

A more efficient would be a regex based on contrast principle within lookaheads when we check for 0 or more characters other than those we need to check for presence and then the required symbol. See a corrected regex containing (?=\D*\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z]):

^(?=\D*\d)(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])[\w~@#$%^&*+=`|{}:;!.?\"()\[\]-]{8,25}$
like image 172
Wiktor Stribiżew Avatar answered Dec 21 '22 23:12

Wiktor Stribiżew