Humpton
Humpton

Reputation: 1519

Regex for names

Just starting to explore the 'wonders' of regex. Being someone who learns from trial and error, I'm really struggling because my trials are throwing up a disproportionate amount of errors... My experiments are in PHP using ereg().

Anyway. I work with first and last names separately but for now using the same regex. So far I have:

^[A-Z][a-zA-Z]+$  

Any length string that starts with a capital and has only letters (capital or not) for the rest. But where I fall apart is dealing with the special situations that can pretty much occur anywhere.

Maybe there's some other way a name can be that I'm no thinking of, but I suspect if I can get my head around this, I can add to it. I'm pretty sure there will be instances where more than one of these situations comes up in one name.

So, I think the bottom line is to have my regex also accept a space, hyphens, ampersands and apostrophes - but not at the start or end of the name to be technically correct.

Upvotes: 27

Views: 129555

Answers (27)

kkyucon
kkyucon

Reputation: 46

This is what I use for full name:

$pattern = "/^((\p{Lu}{1})\S(\p{Ll}{1,20})[^0-9])+[-'\s]((\p{Lu}{1})\S(\p{Ll}{1,20}))*[^0-9]$/u";
  • Supports all languages
  • Common names("Jane Doe", "John Doe")
  • Usefull for composed names("Marie-Josée Côté-Rochon", "Bill O'reilly")
  • Excludes digits(0-9)
  • Only excepts uppercase at beginning of names
  • First and last names from 2-21 characters
  • Adding trim() to remove whitespace
  • Does not except("John J. William", "Francis O'reilly Jr. III")
  • Must use full names, not: ("John", "Jane", "O'reilly", "Smith")

Edit: It seems that both [^0-9] in the pattern above was matching at least a fourth digit/letter in each of either first and/or last names.

Therefore names of three letters/digits could not be matched.

Here is the edited regular expression:

$pattern = "/^(\p{Lu}{1}\S\p{Ll}{1,20}[-'\s]\p{Lu}{1}\S\p{Ll}{1,20})+([^\d]+)$/u";

Upvotes: 0

Aman Godara
Aman Godara

Reputation: 511

^[A-Z][a-z]*(([,.] |[ '-])[A-Za-z][a-z]*)*(\.?)( [IVXLCDM]+)?$

For complete details, please visit THIS post. This regex doesn't allow ampersands.

Upvotes: 1

tk_
tk_

Reputation: 17338

security tip: make sure to validate the size of the string before this step to avoid DoS attack that will bring down your system by sending very long charsets.

Check this out:

^(([A-Za-z]+[,.]?[ ]?|[a-z]+['-]?)+)$

regex

You can test it here : https://regex101.com/r/mS9gD7/46

Upvotes: 5

Jakub Brzezinski
Jakub Brzezinski

Reputation: 1

Following Regex is simple and useful for proper names (Towns, Cities, First Name, Last Name) allowing all international letters omitting unicode-based regex engine.

It is flexible - you can add/remove characters you want in the expression (focusing on characters you want to reject rather than include).

^(?:(?!^\s|[ \-']{2}|[\d\r\n\t\f\v!"#$%&()*+,\.\/:;<=>?@[\\\]^_`{|}~€‚ƒ„…†‡ˆ‰‹‘’“”•–—˜™›¡¢£¤¥¦§¨©ª«¬®¯°±²³´¶·¸¹º»¼½¾¿×÷№′″ⁿ⁺⁰‱₁₂₃₄]|\s$).){1,50}$

Regex matches: from 1 to 50 international letters separated by single delimiter (space -')

Regex rejects: empty prefix/suffix, consecutive delimiters (space - '), digits, new line, tab, limited list of extended ASCII characters

Demo

Upvotes: 0

Charlie Brown
Charlie Brown

Reputation: 11

Try this regex:

^[a-zA-Z'-\s\.]{3,20}\s[a-zA-Z'-\.]{3,20}$

Aomine's answer was quite helpful, I tweaked it a bit to include:

  1. Names with dots (middle): Jane J. Samuels

  2. Names with dots at the end: John Simms Snr.

Also the name will accept minimum 2 letters, and a min. of 2 letters for surname but no more than 20 for each (so total of 40 characters)

Successful Test cases:

D'amalia Jones    
David Silva Jnr.    
Jay-Silva Thompson
Shay .J. Muhanned
Bob J. Iverson

Upvotes: -1

Aomin&#233;
Aomin&#233;

Reputation: 500

you can use this below for names

^[a-zA-Z'-]{3,}\s[a-zA-Z'-]{3,}$

^ start of the string

$ end of the string

\s space

[a-zA-Z'-\s]{3,} will accept any name with a length of 3 characters or more, and it include names with ' or - like jean-luc

So in our case it will only accept names in 2 parts separated by a space


in case of multiple first-name you can add a \s

^[a-zA-Z'-\s]{3,}\s[a-zA-Z'-]{3,}$

Upvotes: 0

Taher Ahmed
Taher Ahmed

Reputation: 221

THE BEST REGEX EXPRESSIONS FOR NAMES:

  • I will use the term special character to refer to the following three characters:
    1. Dash -
    2. Hyphen '
    3. Dot .
  • Spaces and special characters can not appear twice in a row (e.g.: -- or '. or .. )
  • Trimmed (No spaces before or after)
  • You're welcome ;)

Mandatory single name, WITHOUT spaces, WITHOUT special characters:

^([A-Za-z])+$
  • Sierra is valid, Jack Alexander is invalid (has a space), O'Neil is invalid (has a special character)

Mandatory single name, WITHOUT spaces, WITH special characters:

^[A-Za-z]+(((\'|\-|\.)?([A-Za-z])+))?$
  • Sierra is valid, O'Neil is valid, Jack Alexander is invalid (has a space)

Mandatory single name, optional additional names, WITH spaces, WITH special characters:

^[A-Za-z]+((\s)?((\'|\-|\.)?([A-Za-z])+))*$
  • Jack Alexander is valid, Sierra O'Neil is valid

Mandatory single name, optional additional names, WITH spaces, WITHOUT special characters:

^[A-Za-z]+((\s)?([A-Za-z])+)*$
  • Jack Alexander is valid, Sierra O'Neil is invalid (has a special character)

SPECIAL CASE

Many modern smart devices add spaces at the end of each word, so in my applications I allow unlimited number of spaces before and after the string, then I trim it in the code behind. So I use the following:

Mandatory single name + optional additional names + spaces + special characters:

^(\s)*[A-Za-z]+((\s)?((\'|\-|\.)?([A-Za-z])+))*(\s)*$

Add your own special characters

If you wish to add your own special characters, let's say an underscore _ this is the group you need to update:

(\'|\-|\.)

To

(\'|\-|\.|\_)

PS: If you have questions comment here and I will receive an email and respond ;)

Upvotes: 18

Benjamin
Benjamin

Reputation: 1

Have a nice day !

Upvotes: 0

Daan
Daan

Reputation: 1879

This regex is perfect for me.

^([ \u00c0-\u01ffa-zA-Z'\-])+$

It works fine in php environments using preg_match(), but doesn't work everywhere.

It matches Jérémie O'Co-nor so I think it matches all UTF-8 names.

Upvotes: 53

doncadavona
doncadavona

Reputation: 7760

I've come up with this RegEx pattern for names:

/^([a-zA-Z]+[\s'.]?)+\S$/

It works. I think you should use it too.

It matches only names or strings like:

Dr. Shaquil O'Neil Armstrong Buzz-Aldrin

It won't match strings with 2 or more spaces like:

John  Paul

It won't match strings with ending spaces like:

John Paul 

The text above has an ending space. Try highlighting or selecting the text to see the space

Here's what I use to learn and create your own regex patterns:

RegExr: Leanr, Build and Test RegEx

Upvotes: 0

majestic
majestic

Reputation: 19

To improve on daan's answer:

^([\u00c0-\u01ffa-zA-Z]+\b['\-]{0,1})+\b$

only allows a single occurances of hyphen or apostrophy within a-z and valid unicode chars.

also does a backtrack to make sure there is no hyphen or apostrophes at the end of the string.

Upvotes: 1

atif1512
atif1512

Reputation: 1

i think "/^[a-zA-Z']+$/" is not enough it will allow to pass single letter we can adjust the range by adding {4,20} which means the range of letters are 4 to 20.

Upvotes: 0

paviktherin
paviktherin

Reputation: 131

I ran into this same issue, and like many others that have posted, this isn't a 100% fool proof expression, but it's working for us.

/([\-'a-z]+\s?){2,4}/

This will check for any hyphens and/or apostrophes in either the first and/or last name as well as checking for a space between the first and last names. The last part is a little magic that will check for between 2 and 4 names. If you tend to have a lot of international users that may have 5 or even 6 names, you can change that to 5 or 6 and it should work for you.

Upvotes: 0

user669677
user669677

Reputation:

I have used this, because name can be the part of file-patch.

//http://support.microsoft.com/kb/177506
foreach(array('/','\\',':','*','?','<','>','|') as $char)
  if(strpos($name,$char)!==false)
      die("Not allowed char: '$char'");

Upvotes: 0

Tatarasanu Victor
Tatarasanu Victor

Reputation: 654

/([\u00c0-\u01ffa-zA-Z'\-]+[ ]?[*]?[\u00c0-\u01ffa-zA-Z'\-]*)+/;

Try this . You can also force to start with char using ^,and end with char using $

Upvotes: 1

uke
uke

Reputation: 39

This worked for me:

 +[a-z]{2,3} +[a-z]*|[\w'-]*

This regex will correctly match names such as the following:

jean-claude van damme

nadine arroyo-rodriquez

wayne la pierre

beverly d'angelo

billy-bob thornton

tito puente

susan del rio

It will group "van damme", "arroyo-rodriquez" "d'angelo", "billy-bob", etc. as well as the singular names like "wayne".

Note that it does not test that the grouped stuff is actually a valid name. Like others said, you'll need a dictionary for that. Also, it will group numbers, so if that's an issue you may want to modify the regex.

I wrote this to parse names for a MapReduce application. All I wanted was to extract words from the name field, grouping together the del foo and la bar and billy-bobs into one word to make the key-value pair generation more accurate.

Upvotes: 3

Pat Kelly
Pat Kelly

Reputation: 11

You can easily neutralize the whole matter of whether letters are upper or lowercase -- even in unexpected or uncommon locations -- by converting the string to all upper case using strtoupper() and then checking it against your regex.

Upvotes: 1

Abhisek.test
Abhisek.test

Reputation: 11

To add multiple dots in the username use this Regex:

^[a-zA-Z][a-zA-Z0-9_]*\.?[a-zA-Z0-9_\.]*$

String length can be set separately.

Upvotes: 1

PhiLho
PhiLho

Reputation: 41142

Basically, I agree with Paul... You will always find exceptions, like di Caprio, DeVil, or such.

Remarks on your message: in PHP, ereg is generally seen as obsolete (slow, incomplete) in favor of preg (PCRE regexes).
And you should try some regex tester, like the powerful Regex Coach: they are great to test quickly REs against arbitrary strings.

If you really need to solve your problem and aren't satisfied with above answers, just ask, I will give a go.

Upvotes: 3

eyelidlessness
eyelidlessness

Reputation: 63519

While I agree with the answers saying you basically can't do this with regex, I will point out that some of the objections (internationalized characters) can be resolved by using UTF strings and the \p{L} character class (matches a unicode "letter").

Upvotes: 6

Domchi
Domchi

Reputation: 10813

I second the 'give up' advice. Even if you consider numbers, hyphens, apostrophes and such, something like [a-zA-Z] still wouldn't catch international names (for example, those having šđčćž, or Cyrillic alphabet, or Chinese characters...)

But... why are you even trying to verify names? What errors are you trying to catch? Don't you think people know to write their name better than you? ;) Seriously, the only thing you can do by trying to verify names is to irritate people with unusual names.

Upvotes: 3

VirtuosiMedia
VirtuosiMedia

Reputation: 53356

I don't really have a whole lot to add to a regex that takes care of names because there are already some good suggestions here, but if you want a few resources for learning more about regular expressions, you should check out:

Upvotes: 4

Kent Fredric
Kent Fredric

Reputation: 57354

See this question for more related "name-detection" related stuff.

regex to match a maximum of 4 spaces

Basically, you have a problem in that, there are effectively no characters in existence that can't form a legal name string.

If you are still limiting yourself to words without ä ü æ ß and other similar non-strictly-ascii characters.

Get yourself a copy of UTF32 character table and realise how many millions of valid characters there are that your simple regex would miss.

Upvotes: 1

Robert Gamble
Robert Gamble

Reputation: 109022

^[A-Z][a-zA-Z '&-]*[A-Za-z]$ 

Will accept anything that starts with an uppercase letter, followed by zero or more of any letter, space, hyphen, ampersand or apostrophes, and ending with a letter.

Upvotes: 1

Matthew Scharley
Matthew Scharley

Reputation: 132254

  • Hyphenated Names (Worthington-Smythe)

Add a - into the second character class. The easiest way to do that is to add it at the start so that it can't possibly be interpreted as a range modifier (as in a-z).

^[A-Z][-a-zA-Z]+$
  • Names with Apostophies (D'Angelo)

A naive way of doing this would be as above, giving:

^[A-Z][-'a-zA-Z]+$

Don't forget you may need to escape it inside the string! A 'better' way, given your example might be:

^[A-Z]'?[-a-zA-Z]+$

Which will allow a possible single apostrophe in the second position.

  • Names with Spaces (Van der Humpton) - capitals in the middle which may or may not be required is way beyond my interest at this stage.

Here I'd be tempted to just do our naive way again:

^[A-Z]'?[- a-zA-Z]+$

A potentially better way might be:

^[A-Z]'?[- a-zA-Z]( [a-zA-Z])*$

Which looks for extra words at the end. This probably isn't a good idea if you're trying to match names in a body of extra text, but then again, the original wouldn't have done that well either.

  • Joint Names (Ben & Jerry)

At this point you're not looking at single names anymore?

Anyway, as you can see, regexes have a habit of growing very quickly...

Upvotes: 45

Paul Tomblin
Paul Tomblin

Reputation: 182782

Give up. Every rule you can think of has exceptions in some culture or other. Even if that "culture" is geeks who like legally change their names to "37eet".

Upvotes: -1

Osama Al-Maadeed
Osama Al-Maadeed

Reputation: 5695

if you add spaces then "He went to the market on Sunday" would be a valid name.

I don't think you can do this with a regex, you cannot easily detect names from a chunk of text using a regex, you would need a dictionary of approved names and search based on that. Any names not on the list wouldn't be detected.

Upvotes: 0

Related Questions