Ferdinand Rosario Ferdinand Rosario - 5 months ago 15
Ruby Question

Password policy using regular expression Ruby

I have created a Regular Expression

^(?=.*[a-z]{2})(?=.*[A-Z]{2})(?=.*\d{2})(?=.*([%]{2})).{8,10}$


which help me to restrict 2 Lower Case + 2 Uppercase + 2 Digit+ special character , and tge total length should be between 8-10.
Ex: aaAA12%% will be a valid string. but, I need to make aAaA%3%3 also a valid string.
how to do the negative of lookahead match in ruby

Expectation: The string should contain exact number of uppercase,lowercase,digit & specific special character irrespective of their order.It can be in any order followed with UpperCase and lowwercase .

Ex: 2 uppercase,2lowercase,2digit,+special character ( aA1B%b2&)

Answer

My understanding is that you wish to confirm that a string contains, in any order:

  • 2 lowercase letters
  • 2 uppercase letters
  • 2 digits
  • 1 (specified) "special" character and
  • between 1 and 3 additional characters (which may include letters, digits and the special character)

Here are a couple of approaches.

Use a regex after sorting

Code

def confirm(str, special)
  r = /
      [A-Z]{2,}   # match at least 2 uppercase letters
      [a-z]{2,}   # match at least 2 lowercase letters
      \d{2,}      # match at least 2 digits
      #{special}  # match the special character
      /x          # free-spacing regex definition mode
  str.size.between?(8,10) && str.each_char.sort_by do |c|
    case c
    when /[A-Z]/ then 0
    when /[a-z]/ then 1
    when /\d+/   then 2
    when special then 3
    else              4
    end
  end.join =~ r ? true : false 
end

Examples

confirm("aaAA12%%",    "%") #=> true 
confirm("aAaA%3%3",    "%") #=> true 
confirm("2aAaA%3%3",   "%") #=> true 
confirm("2aA1bA%A%3",  "%") #=> true 
confirm("2aA1bA%4%3",  "%") #=> true 
confirm("aAaaA%3a%3",  "%") #=> true 
confirm("2aAaA%3%3",   "%") #=> true 
confirm("aaA12%4%",    "%") #=> false
confirm("aAA12%4%",    "%") #=> false
confirm("aaAA1%aa%",   "%") #=> false 
confirm("2aA1b4A%3%3", "%") #=> false 
confirm("aA1bA%3",     "%") #=> false 

Count characters

Code

def confirm(str, special)
  str.size.between?(8,10) && str.scan(/[A-Z]/).size >= 2 &&
    str.scan(/[a-z]/).size >= 2 && str.scan(/\d/).size >= 2 &&
    str.count(special) >= 1
end 

Examples

confirm("aaAA12%%",    "%") #=> true 
confirm("aAaA%3%3",    "%") #=> true 
confirm("2aAaA%3%3",   "%") #=> true 
confirm("2aA1bA%A%3",  "%") #=> true 
confirm("2aA1bA%4%3",  "%") #=> true 
confirm("aAaaA%3a%3",  "%") #=> true 
confirm("2aAaA%3%3",   "%") #=> true 
confirm("aaA12%4%",    "%") #=> false
confirm("aAA12%4%",    "%") #=> false
confirm("aaAA1%aa%",   "%") #=> false 
confirm("2aA1b4A%3%3", "%") #=> false 
confirm("aA1bA%3",     "%") #=> false 
Comments