skip to Main Content

I have a code in JS that does the following check based on regex rules as below:

let nameCriteria = {
    uppercase: {regex: /[A-Z]/, description: 'At least one uppercase letter'},
    lowercase: {regex: /[a-z]/, description: 'At least one lowercase letter'},
    digit: {regex: /^[^0-9]+$/, description: 'Digits are not allowed'},
    special: {regex: /^[^&~_%#@+=<>?!.,;:"`^(){}*|/\$]*$/, description: 'Special symbols are not allowed'},
    length: {test: userName => userName.length >= 2 && userName.length <= 40, description: 'Should be 2 or more and 40 or less characters'},
    space: {regex: /^S*$/, description: 'Space is not allowed'}
};

I tried to convert it to PHP so al I could do is this so far:

/^(?=.*[a-z])(?=.*[A-Z]).{2,40}$/

It matches the first two conditions At least one uppercase & one lower case and a length of a min of 2 and a max of 40.
Any help for the rest please?

2

Answers


  1. Based on conversation within comments and based on question, basically, to answer the question your regex should look like this:

    /^(?=.*[a-z])(?=.*[A-Z])(?!.*[0-9])(?!.*[&~_%#@+=<>?!.,;:"`^(){}*|/\$])(?!.*s).{2,40}$/
    

    (?=.*[a-z]): Guarantees a minimum of one letter in lowercase.

    (?=.*[A-Z]): Ensures at least one uppercase letter.

    (?!.*[0–9]): Verifies the absence of digits.

    (?!.*[&~_%#@+=<>?!.,;:"^(){}*|/$])}: Verifies the absence of special symbols.

    (?!.*s): Verifies the absence of spaces.

    ..{2,40}: Assures that the character count falls between 2 and 40.

    Heads up: Regex can get rather complicated and difficult to manage, particularly when you combine several lookaheads for various criteria. Performing some of these tests (checking) independently is frequently more readable and manageable, particularly if you have distinct error messages or handling for each condition.

    UPDATE:
    Because OP is stating that my regex pattern is not taking Foobar into consideration, I wrote out simple script to test it out. But I’d go with Wiktor’s regex pattern because of simplicity and readability (I am not arguing over that).

       import re
    
    regex_wiktor = r"^(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])[a-zA-Z]{2,40}$"
    regex_str1ng = r"^(?=.*[a-z])(?=.*[A-Z])(?!.*[0-9])(?!.*[&~_%#@+=<>?!.,;:"`^(){}*|/\$])(?!.*s).{2,40}$"
    
    # Test strings
    test_strings = ["Foobar", "fooBar", "Foobar123", "foo bar", "Foobar!", "Fo", "F" * 41, "foobar", "FOOBAR"]
    
    def test_regex(pattern, test_strings):
        return {string: bool(re.match(pattern, string)) for string in test_strings}
    
    results_wiktor = test_regex(regex_wiktor, test_strings)
    results_str1ng = test_regex(regex_str1ng, test_strings)
    
    print(results_wiktor, results_str1ng)
    

    Results:

    ({'Foobar': True,
      'fooBar': True,
      'Foobar123': False,
      'foo bar': False,
      'Foobar!': False,
      'Fo': True,
      'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF': False,
      'foobar': False,
      'FOOBAR': False},
     {'Foobar': True,
      'fooBar': True,
      'Foobar123': False,
      'foo bar': False,
      'Foobar!': False,
      'Fo': True,
      'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF': False,
      'foobar': False,
      'FOOBAR': False})
    

    UPDATE 2:
    I am withdrawing my words, "Foobarn" when using Wiktor Stribiżew’s regex pattern is matched as a valid string – which could be a potential issue if newline characters are not intended to be allowed; WHILE mine regex pattern doesn’t see it as valid.

    Login or Signup to reply.
  2. You’re "not allowed special symbols", regex is a little incomplete.
    The regex for ASCII Special characters is this [!-/:-@[]-`{-~] .

    And it allows all ASCII A-Z, a-z, 0-9, and control codes,
    which overlaps some of what you allow already A-Z, a-z and 0-9.

    Never the less you can put groups flags on any part that don’t match.
    this w`ill allow you to map the errors then display that info to the user.

    A single pass regex is all that’s needed.:

    ^(?=.*[A-Z]|())(?=.*[a-z]|())(?=[^0-9rn]+$|())(?=[^&~_%#@+=<>?!.,;:"`^(){}*|/\$rn]+$|())(?=.{2,40}$|()).+
    

    https://regex101.com/r/NyS8bP/1

    This represents exactly what the JS code was doing. There is no other efficient way.
    After each match, walk the capture group matched, start from 1 to 5.
    Each is mapped to an error. Only the ones matched are in error.
    Use an if, then else sequence.

    Overview

    ^ 
    (?=
       .* [A-Z] 
     | ( )                # (1), No cap letter found
    )
    (?=
       .* [a-z] 
     | ( )                # (2), No lower case letter found
    )
    (?=
       [^0-9rn]+ $ 
     | ( )                # (3), A not allowed number found
    )
    (?=
       [^&~_%#@+=<>?!.,;:"`^(){}*|/\$rn]+ $  
     | ( )                # (4), A not allowed special character found
    )
    (?=
       .{2,40} $ 
     | ( )                # (5), The alloewd range of characters exceeded
    )
    .+ 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search