tags:

views:

1142

answers:

6

Hi,

I have a regular expression to match a persons name.

So far I have ^([a-zA-Z\'\s]+)$ but id like to add a check to allow for a maximum of 4 spaces. How do I amend it to do this?

Edit: what i meant was 4 spaces anywhere in the string

+4  A: 

Screw the regex.

Using a regex here seems to be creating a problem for a solution instead of just solving a problem.

This task should be 'easy' for even a novice programmer, and the novel idea of regex has polluted our minds!.

1: Get Input    
2: Trim White Space
3: If this makes sence, trim out any 'bad' characters. 
4: Use the "split" utility provided by your language to break it into words
5: Return the first 5 Words.

ROCKET SCIENCE.

replies

what do you mean screw the regex? your obviously a VB programmer. Regex is the most efficient way to work with strings. Learn them.

No. Php, toyed a bit with ruby, now going manically into perl.

There are some thing ( like this case ) where the regex based alternative is computationally and logically exponentially overly complex for the task.

I've parse entire php source files with regex, I'm not exactly a novice in their use.

But there are many cases, such as this, where you're employing a logging company to prune your rose bush.

I could do all steps 2 to 5 with regex of course, but they would be simple and atomic regex, with no weird backtracking syntax or potential for recursive searching.

The steps 1 to 5 I list above have a known scope, known range of input, and there's no ambiguity to how it functions. As to your regex, the fact you have to get contributions of others to write something so simple is proving the point.

I see somebody marked my post as offensive, I am somewhat unhappy I can't mark this fact as offensive to me. ;)

Proof Of Pudding:

sub getNames{
    my @args = @_;
    my $text = shift @args;
    my $num  = shift @args;

    # Trim Whitespace from Head/End
    $text =~ s/^\s*//;
    $text =~ s/\s*$//;

    # Trim Bad Characters (??)
    $text =~ s/[^a-zA-Z\'\s]//g;

    # Tokenise By Space 
    my @words = split( /\s+/, $text );

    #return 0..n 
    return @words[ 0 .. $num - 1 ];
} ## end sub getNames

print join ",", getNames " Hello world     this is a    good test", 5;
>> Hello,world,this,is,a

If there is anything ambiguous to anybody how that works, I'll be glad to explain it to them. Noted that I'm still doing it with regexps. Other languages I would have used their native "trim" functions provided where possible.


Bollocks -->

I first tried this approach. This is your brain on regex. Kids, don't do regex.


This might be a good start

/([^\s]+
    (\s[^\s]+
      (\s[^\s]+
        (\s[^\s]+
          (\s[^\s]+|)
         |)
       |)
    |)
  )/

( Linebroken for clarity )

/([^\s]+(\s[^\s]+(\s[^\s]+(\s[^\s]+|)|)|))/

( Actual )

I've used [^\s]+ here instead of your A-Z combo for succintness, but the point is here the nested optional groups

ie:

(Hello( this( is( example))))
(Hello( this( is( example( two)))))
(Hello( this( is( better( example))))) three
(Hello( this( is()))))
(Hello( this()))
(Hello())

( Note: this, while being convoluted, has the benefit that it will match each name into its own group )

If you want readable code:

  $word = '[^\s]+'; 
  $regex = "/($word(\s$word(\s$word(\s$word(\s$word|)|)|)|)|)/";

( it anchors around the (capture|) mantra of "get this, or get nothing" )

Kent Fredric
Don't start flame wars on stackoverflow.
andreas buykx
@Sir Psycho: no, his way is a bit longer in code lines, but much clearer to understand and resilient. Regexes are nice tools, but you have to think when and when not to use them.
Adriano Varoli Piazza
+2  A: 

^([a-zA-Z']+\s){0,4}[a-zA-Z']+$

This assumes you want 4 spaces inside this string (i.e. you have trimmed it)

Edit: If you want 4 spaces anywhere I'd recommend not using regex - you'd be better off using a substr_count (or the equivalent in your language).

I also agree with pipTheGeek that there are so many different ways of writing names that you're probably best off trusting the user to get their name right (although I have found that a lot of people don't bother using capital letters on ecommerce checkouts).

Greg
+1 for conciseness, and for re-tagging to eliminate ^rege(x){1,2}$
Adam Liss
This does not match what he asked though. Based on what he asked you could have 2 spaces in a row for example.
Brian R. Bondy
He did say he was matching names. Nobody's name has two spaces in a row!
Greg
It depends on how you interpret the question. Based on the upvotes I think more people agree with me that a person's name should not have consecutive whitespace.
Greg
RoBorg you have no idea of where the input is coming from. For all you know it might be sent to him in a form where the possibility of 4 consequative spaces happens and he needs to make a match based on that. For all we know we will do post-match clean up of the name once its been located.
TheCodeJunkie
What RoBorg here has matches "bob", "bob smith", "bob mc smith", etc. The question was formed very poorly... this answer is most likely what he REALLY wanted. The only bugs are that single char names won't match, and it can start with a space (as BKB mentioned).
Timothy Khouri
Sorry, BKB, but you're wrong. That regex matches ((one or more letters or apostrophes) followed by a whitespace character) zero to four times, followed by (one or more letters or apostrophes). It's not how I would have written it, but it does what Sir P. requested.
Alan Moore
+2  A: 

@Sir Psycho : Be careful about your assumptions here. What about hyphenated names? Dotted names (e.g. Brian R. Bondy) and so on?

ZombieSheep
Additionaly, people can have other letters than just a-z in their names.
JacquesB
+9  A: 

Don't attempt to regex validate a name. People are allowed to call themselves what ever they like. This can include ANY character. Just because you live somewhere that only uses English doesn't mean that all the people who use your system will have English names. We have even had to make the name field in our system Unicode. It is the only Unicode type in the database.

If you care, we actually split the name at " " and store each name part as a separate record, but we have some very specific requirements that mean this is a good idea.

PS. My step mum has 5 spaces in her name.

pipTheGeek
We are developing an intranet app so English is all that matters.
Sir Psycho
You don't have any foreign employees?
pipTheGeek
The time Loïc Dupont, Hernán Núñez and Alberto Gonçalves start working for his company, there will be trouble. Small trouble, but...
Adriano Varoli Piazza
"People are allowed to call themselves what ever they like" I sort of agree, but there must be validation of some sort. A name with % sign is not valid regardless of what part of the earth your from.
Sir Psycho
@sir psycho - Probably true. But I don't believe there is anything (other than social convention) that prevents someone naming themselves "like %". If your users are continually typing incorrect puntuation into names then I would probably issue a warning for any name containing any character other than a-z and ' but I would be very hesitant about actually forbidding any characters.
pipTheGeek
+4  A: 
^                    # Start of string
(?!\S*(?:\s\S*){5})  # Negative look-ahead for five spaces.
([a-zA-Z\'\s]+)$     # Original regex

Or in one line:

^(?!(?:\S*\s){5})([a-zA-Z\'\s]+)$

If there are five or more spaces in the string, five will be matched by the negative lookahead, and the whole match will fail. If there are four or less, the original regex will be matched.

MizardX
And consider removing extra spaces before you start: s/ +/ /g;
Jonathan Leffler
Or, better, s/\s\s+/ /g; which matches any white space, not just blank.
Jonathan Leffler
+1  A: 

Here's the answer that you're most likely looking for:

^[a-zA-Z']+(\s[a-zA-Z']+){0,4}$

That says (in English): "From start to finish, match one or more letters, there can also be a space followed by another 'name' up to four times."

BTW: Why do you want them to have apostrophes anywhere in the name?

Timothy Khouri
Yes, but this regex allows names consisting entirely of apostrophes. But there's no such thing as a regex for validating human names, so everyone's just using the OP's regex as the basis for their suggestions.
Alan Moore
This regex is functionally equivalent to RoBorg's, but putting the required component first instead of last makes the intention clearer, and probably makes it more efficient as well.
Alan Moore