1

Looking for a regex to check a valid English name, i.e.:

  • A-Z, a-z, space only
  • First name, (optional) Middle name, Last name

An acceptable example: John von Neumann

Thanks!

EDIT (added checking code):

#!/usr/bin/php

<?php

    function check_name($regex, $name)
    {
        $rc = 'Bad';
        if (preg_match($regex, $name)) {    
            $rc = 'Good';
        }
        return '|' . $name . '| ' . $rc . "\n";
    }

    $regex = '/(?:[A-Za-z]+(?:\s+|$)){2,3}/';
    echo check_name($regex, 'First');
    echo check_name($regex, 'First Last');
    echo check_name($regex, 'Two  Spaces');
    echo check_name($regex, 'First Middle Last');
    echo check_name($regex, 'First Middle Last Fourth');
    echo check_name($regex, 'First 123');

?>
ohho
  • 50,879
  • 75
  • 256
  • 383
  • 7
    There are far more things that are acceptable as names outside of your specifications, are you sure those rules are what you want? For instance, what about "John O'Malley" or similar? – Amber Sep 02 '10 at 03:59
  • 2
    What Amber said, plus hyphenated names. :-) (Say I, who has such a name. :-P) – C. K. Young Sep 02 '10 at 04:00
  • 1
    What about my poor friend Böb. – Russell Dias Sep 02 '10 at 04:03
  • @Artefacto I tried [\w]+ with no luck. – ohho Sep 02 '10 at 04:03
  • @Amber @Chris Jester-Young can be safely ignored. In my case, I am checking the English name of a Chinese name, which typically does not contain \' or European characters. I just want to make sure the users do not fill in the Chinese name in the English name field. – ohho Sep 02 '10 at 04:05
  • Actually, Chinese pinyin can contain apostrophes, to disambiguate between, say, Xi'an (two words) versus Xian (one word). If you want to enforce, say, ASCII only, you can use the `[:ascii:]` character class. – C. K. Young Sep 02 '10 at 04:09
  • @ohho O man! That thinking is called over-optimization and it will bite you in the a$$, guaranteed. – Theodore R. Smith Sep 02 '10 at 04:10
  • What about people with two middle names? This question is poorly phrased at the moment. – Shaggy Frog Sep 02 '10 at 04:14
  • @hopeseekr thanks for reminding. I will add more complex business rules once I got the simple `regex` running. Maybe I should change the title of this question to `PHP regex to check a simplified version of a English name`. – ohho Sep 02 '10 at 04:30
  • I have a friend who is `... the 3rd` (number in name) – Peter Ajtai Sep 02 '10 at 04:31
  • @Chris Jester-Young does `([:ascii:]+){2,3}` work? – ohho Sep 02 '10 at 04:34
  • @ohho: Spaces are ASCII too. If you want to enforce 2 or 3 words, then maybe something like `[^[:^ascii:]\s]+(\s+[^[:^ascii:]\s]+){1,2}` should work. (Not tested.) – C. K. Young Sep 02 '10 at 04:40

4 Answers4

7

If the rules you've stated are actually what you want, the following would work:

/^(?:[A-Za-z]+(?:\s+|$)){2,3}$/

However, there are quite a few real-life names that don't fit in these rules, like "O'Malley", "Jo-Jo", etc.

You can of course extend this regex fairly easily to allow other characters - just add them into the brackets. For instance, to allow apostrophes and dashes, you could use [A-Za-z'-] (the - has to be at the end, or it will be interpreted as a range).

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 1
    +1: For providing working regex for the OP requirement rules. – shamittomar Sep 02 '10 at 04:04
  • If you add the rules to allow for names like Teal'c Malquet, Jack O'Neill and Jennifer McKay-Keller ;-) – Theodore R. Smith Sep 02 '10 at 04:07
  • @Amber thanks! It seems that the regex allows a single string (e.g. `John` is consider as OK). I'd like to check both first name and last name (i.e. two strings separated by a space) compulsory. – ohho Sep 02 '10 at 04:25
  • @Amber - it seems that the regex allows a four-part string, e.g.: `First Middle Last Fourth`, which should not be allowed. Acceptable string should be either two or three parts. – ohho Sep 03 '10 at 01:14
  • It shouldn't... the grouping only allows one contiguous set of letters (in the `[A-Za-z]+` part), and that section only gets repeated up to 3 times (`{2,3}` = 2 to 3). – Amber Sep 03 '10 at 03:28
  • Just to make sure, I've added a `^` to the beginning of the regex, perhaps you're only partial-matching the string? – Amber Sep 03 '10 at 03:32
2

Your name is going to fail for the O'Neil's out there. Also the Webb-Smiths and the like.

Use @Amber's modified:

/(?:[A-Za-z.'-]+\s*){2,3}/

Theodore R. Smith
  • 21,848
  • 12
  • 65
  • 91
0

You can try:

if(preg_match('/^([a-z]+ ){1,2}[a-z]+$/i',trim($input))) {
  // valid full name.
}

As noted by others, it will allow NO punctuations in the name!!

codaddict
  • 445,704
  • 82
  • 492
  • 529
0

This is a bad idea. People may have various punctuation characters in their names, such as dashes and apostrophes. They may also have accented or foreign letters. Also, the number of middle names can vary greatly.

Adam Crume
  • 15,614
  • 8
  • 46
  • 50
  • Please focus on the _requirement_ of this question, rather than the definition of an English name ... thx – ohho Sep 03 '10 at 01:51