简体   繁体   中英

How can I add multiple conditions to regex?

I have tried many times but could not find the solution.

One of the rules is if string ends with digit then it must contain one more digit in string anywhere

These are the rules I have - as you can see in the console my test does not work as expected

/* password length 6-80, */
/* if ends with digit then must contain two digit, */
/* 1 upper case character, 1 lowercase character, 1 digit and 1 special character. */
/* If password starts with uppercase character then 2 uppercase character are required. */

 var re = /(?=.*\\d)(?=.*[az])(?=.*[AZ])(?=.*[-_*&^%$#@!~])((?=\\b[AZ]).*[AZ].*[AZ].*|(?!\\b[AZ]))((?=.*\\d$).*\\d.*\\d.*|(?!.*\\d$)){6,80}/g; console.log("false?",re.test('Aa@sasA1')); console.log("true?",re.test('Aa@sa1sA1')); 

 var re = /^(?=.*\\d)(?=.*[az])(?=.*[AZ])(?=.*[-_*&^%$#@!~])(?=[AZ].*[AZ]|[^AZ])(?=.*\\d.*\\d$|.*\\D$).{6,80}$/; console.log("false?",re.test('Aa@sasA1')); console.log("true?",re.test('Aa@sa1sA1')); 

Explanation:

(?=[A-Z].*[A-Z]|[^A-Z]) : first character: 1 upper and another one OR not upper
(?=.*\d.*\d$|.*\D$)     : last character: digit and another one before OR not a digit

That requirements look weird. Please have a read to Microsoft Password Guidance .

Must contain one digit + must contain one digit which is not last character when last is a digit = must contain one digit before last character. In other words: replace (?=.*\\d) with (?=.*\\d.) .

Almost same for uppercase, true requirement is having an uppercase which is not first character.

 var re = /^(?=.*\\d.)(?=.*[az])(?=.+[AZ])(?=.*[-_*&^%$#@!~]).{6,80}$/; console.log("false?",re.test('Aa@sasA1')); console.log("false?",re.test('Aa@sasa1')); console.log("true?",re.test('Aa@sa1sA1')); 

We also can add some contrast to prevent unneeded backtracking. As quantifiers, either greedy or lazy, can lead backtracking, better option is to work around character classes.

Considering first lookahead we need to match a digit anywhere before the last character. (?=.*\\d.) then becomes (?=\\D*\\d.) , matching non digits first preventing backtracking.

Following that principle, the whole regex becomes:

^(?=\D*\d.)(?=[^a-z]*[a-z])(?=.[^A-Z]*[A-Z])(?=[^-_*&^%$#@!~]*[-_*&^%$#@!~]).{6,80}$

That way, when user enters a particularly long string, failing will occur fast (have a look to The elements of Regex Style ).

 var re = /^(?=\\D*\\d.)(?=[^az]*[az])(?=.[^AZ]*[AZ])(?=[^-_*&^%$#@!~]*[-_*&^%$#@!~]).{6,80}$/; console.log("false?",re.test('Aa@sasA1')); console.log("false?",re.test('Aa@sasa1')); console.log("true?",re.test('Aa@sa1sA1')); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM