SitePoint Sponsor

User Tag List

Results 1 to 13 of 13
  1. #1
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    perl regular expression for hyphenated names

    Hi,

    Trying to write a regular expression that will only allow a name of between 1 and 20 letters, but is ok with hyphens.

    This:

    Code:
    while($firstName !~ m/^([a-zA-Z]\-*[a-zA-Z]*){1,20}$/)
    allows for the hyphens but doesn't return an error when I type in more than 20 letters.

    Completely stuck. Please help!

    Many thanks to all who do so.

  2. #2
    SitePoint Wizard bronze trophy KevinR's Avatar
    Join Date
    Nov 2004
    Location
    Moon Base Alpha
    Posts
    1,053
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    maybe:

    Code:
    while ( $firstName !~ m/^([a-zA-Z]+(-[a-zA-Z]*)){1,20}$/ ){

  3. #3
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks Kevin. I'll give it a go when I get home and let you know.

  4. #4
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Didn't work. Threw up a syntax error near ){.

  5. #5
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Apologies Kevin. Here follows a lesson in the dangers of copy and paste:

    Code:
    whilewhile($firstName ....etc
    is never going to work, is it?

    I need one of those "are you sure" boxes to pop up every time I hit submit reply. Cos I never am.

    There is no syntax error in your code.

    The problem I originally had is still there though. If I type a name with more than 20 letters in it, the error trap picks it up. However, if I type a name with a hyphen in it, it doesn't matter if there are 120 characters are in it, the error trap lets it on through.

  6. #6
    SitePoint Wizard bronze trophy KevinR's Avatar
    Join Date
    Nov 2004
    Location
    Moon Base Alpha
    Posts
    1,053
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    maybe:

    Code:
    my $firstName = '';
    until ( $firstName =~ m/^([a-zA-Z]-?[a-zA-Z]){1,20}$/ ){
       print "Enter a name: \n";
       chomp ($firstName = <STDIN>);
    }

    or:

    Code:
    my $firstName = '';
    while ( $firstName !~ m/^([a-zA-Z]-?[a-zA-Z]){1,20}$/ ){
       print "Enter a name: \n";
       chomp ($firstName = <STDIN>);
    }

  7. #7
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm afraid that didn't work either. That method rejects anything that hasn't got the hyphen.

    I changed it to:

    Code:
    ($firstName !~ m/^([a-zA-Z]-?[a-zA-Z]*){1,20}$/)
    i.e. with an asterisk after the second a-zA-Z, but that lets me put in more than 20 characters again.

    It's starting to REALLY annoy me now. Your method looks right, according to everything I have read about regular expressions it is right, but it doesn't work. Do you thinks it's possible?

  8. #8
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can I just clarify. Yes, the method you suggested does reject a name without a hyphen, but only if it less than 20 characters. If it is more than 20 characters, without a hyphen, it goes through!

    Is there something wrong with my computer? We can clearly see a bit of code that goes like this:

    Code:
    {1,20}
    How the hell does this let stuff of 21 letters through?

    The mist is getting thicker.

  9. #9
    SitePoint Wizard bronze trophy KevinR's Avatar
    Join Date
    Nov 2004
    Location
    Moon Base Alpha
    Posts
    1,053
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not really sure why it's no working, must have something to do with nested quantifiers messing up the last quantifier or my just not understanding why, but this should work:

    Code:
    my @names = qw(
    wwwwwwwwwwwwwww
    wwwwwwwwwww-www
    ww-wwwwwwwwwwwww
    -wwwwwwwwww
    -wwwwwwwwwwwwwwwwwwwwwwwwwww
    wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
    ww-ww-ww-www-ww-
    w
    );
    
    foreach my $firstNames (@names) {
       if (length $firstNames < 21 && $firstNames =~ m/^[a-zA-Z]+(?:-?[a-zA-Z])*$/ ){
          print "[pass] : $firstNames\n";
       }
       else {
          print "[fail] : $firstNames\n"
       }
    }
    maybe someone else can explain the problem with the other regexps. Run a bunch of potential names through it and see how well it catches exceptions.
    Last edited by KevinR; Feb 14, 2007 at 19:08. Reason: chnaged: m/^[-a-zA-Z]+(?:-?[a-zA-Z])*$/

  10. #10
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for all your help Kevin. Very much appreciated. That method seems to work.

  11. #11
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have refined your method to make it look more like what we were after earlier:

    Code:
    print("Please enter first name: ");
    $firstName=<STDIN>;
    chomp($firstName);
    while(length $firstName > 20 || $surname !~ m/^[a-zA-Z]+-?[a-zA-Z]+$/)
    {
    	print("Invalid first name. Please try again: ");
    	$firstName=<STDIN>;
    	chomp($firstName);
    }
    What do you think?

  12. #12
    SitePoint Wizard bronze trophy KevinR's Avatar
    Join Date
    Nov 2004
    Location
    Moon Base Alpha
    Posts
    1,053
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by palgrave View Post
    What do you think?

    the conditional is checking two different scalars: $firstName and $surname, is that what you want to do?

    A couple of things, you don't need parenthesis around print statements, you can chomp <STDIN> and assign it to a variable in one step, and you should be using "strict" and might want to use "warnings" and "diagnostics" as well:

    Code:
    print "Please enter first name: ";
    chomp($firstName=<STDIN>);
    while(length $firstName > 20 || $surname !~ m/^[a-zA-Z]+-?[a-zA-Z]+$/)
    {
    	print "Invalid first name. Please try again: ";
    	chomp($firstName=<STDIN>);
    }
    a bit more perlish way to write this:

    Code:
    print "Please enter first name: ";
    chomp($firstName=<STDIN>);
    while(1)
    {
       if (length $firstName > 20 || $surname !~ m/^[a-zA-Z]+-?[a-zA-Z]+$/) {
          print "Invalid first name. Please try again: ";
          chomp($firstName=<STDIN>);
       }
       #some other stuff here 
       last;
    }
    this way you can include more conditions or do other things and until all conditions are true the "while" loop continues. When all conditions are true, "last" breaks you out of the "while" loop.


    edit: that is the number one in parenthesis: while(1)
    Last edited by KevinR; Feb 15, 2007 at 17:17.

  13. #13
    SitePoint Addict palgrave's Avatar
    Join Date
    Jan 2006
    Posts
    357
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    the conditional is checking two different scalars: $firstName and $surname, is that what you want to do?
    No. Another typo.

    Thanks for the advice. I will change the program accordingly. I have only started learning Perl, and it is the steepest learning curve I have had to roll up since I took an interest in the web.

    I really appreciate you taking the time to go through this with me.

    Many thanks.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •