SupremeA SupremeA - 1 month ago 19
Ruby Question

Regex for Name in Ruby

I know this question has been asked a lot but I need a RegEx for a name validator.

The only requirements are letters are okay, No numbers, and no special characters other than 2 and the spaces cannot be at the beginning or end, the "-" and "`" are allowed also. Everything else would be invalid.

All the other answers seem to ask for a lot more and seem to get too complicated.

Currently I am using

/^([^\d\W]|[-])*$/


But this fails with the space

Sample data

Pass:

Susan Johnson,
Stephanie Le'Sean,
John Pierre'-Frank


Fail:

Ricky2Good,
Jean,stewie,
Mike@dude,
Jim. McNeil

Answer

I've assumed that for a string to be valid, it may contain only uppercase and lowercase letters, apostrophes, dashes and at most two spaces, provided the spaces are not at the beginning or end of the string.

STR= "-a-z'"

r = /
    \A           # match beginning of string
    (?:          # begin non-capture group
      [#{STR}]+  # match 1+ letters, "-" or "'"
      |          # or
      [#{STR}]+\s[#{STR}]*\s?[#{STR}]+
                 # match 1+ letters, "-" or "'", space, 0+ letters, "-" or "'",
                 # optional space, 1+ letters, "-" or "'"
    )            # end non-capture group
    \z           # match end of string
    /ix          # case-indifferent and free-spacing regex definition modes
      #=> /
          \A           # match beginning of string
          (?:          # begin non-capture group
            [-a-z']+   # match 1+ letters, "-" or "'"
            |          # or
            [-a-z']+\s[-a-z']*\s?[-a-z']+
                       # match 1+ letters, "-" or "'", space, 0+ letters, "-" or "'",
                       # optional space, 1+ letters, "-" or "'"
          )            # end non-capture group
          \z           # match end of string
          /ix 

If I did not use free-spacing mode to define the regex it would look like this:

r = /\A(?:[-a-z']+|[-a-z']+\s[-a-z']*\s?[-a-z']+)\z/i 

"a B-' v"    =~ r #=> 0
"aB-'v"      =~ r #=> 0
"aB-'1v"     =~ r #=> nil
"a B-'1  v"  =~ r #=> nil
" a B-1v"    =~ r #=> nil 

The question asks for a regex to validate names. Using a regex may be the best, but it's not the only way. If the question is really how to validate names--using a regex or otherwise--it should be stated in a way that doesn't stipulate a particular approach. Here's one way to validate without using a regex.

GOOD_CHARS = ('a'..'z').to_a.join << '`-'
  #=> "abcdefghijklmnopqrstuvwxyz"

def validate(str)
  return false if str.empty? || (str[0]==' ' || str[-1]==' ')
  nbr_spaces = str.count(' ')
  return false if nbr_spaces > 2 
  str.downcase.count(GOOD_CHARS) + nbr_spaces == str.size
end

validate "a B-` v"   #=> true
validate "aB-`v"     #=> true
validate "aB-`1v"    #=> false 
validate "a B-`1  v" #=> false 
validate " a B-`1v"  #=> false