locked
Regular Expressions - Plz Help

    Question

  • Hi All,

    I am new in regular expressions so please forgive my level of question.
    I have a regular expression for validating special characters in Username is:

    ^((\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+$

    Can anyone help me by updating the given expression so it can not accept "_" as single character (can not allow only "_" as Username) and also can not accept "_" as first and last character of Username.

    Thanks in advance.

    Monday, March 30, 2009 8:02 AM

Answers

  • VisioGuy,
    Please look at my earlier post.  It uses "look-around" to handle the your original requirements.  If you understand how "look-around" works, you can easily my modifications to it below.  I also limited it to 30 characters and changed the pattern to simplify.  Please note, the RegularExpressionValidator will not report an error if the control's text is empty (by control design), you must separately detect and reject blank usernames.

    Here's the updated pattern.

    (?!^[_.-].*$)(?!^.*[_.-]$)(^[a-zA-Z0-9_.-]{1,30}$)
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    • Marked as answer by VisioGuy Thursday, April 02, 2009 7:01 AM
    Wednesday, April 01, 2009 11:43 AM

All replies

  • please try
    ^((\w|\d)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+(\w|\d)$
    
    

    HTH
    Ivo Stoykov
    • Proposed as answer by ivostoykov Monday, March 30, 2009 8:48 AM
    Monday, March 30, 2009 8:47 AM
  • I did check that expression but unfortunately it did not work (allowing to accept only single character "_" as Username and accepting "_" as first and last character in Username as well).

    Any other idea?

    Thanks

    Monday, March 30, 2009 10:08 AM

  • How do make the check?

    Meanwhile a variation of the above:
    ^([^_](\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)(\.)?)+[^_]$
    HTH
    Ivo Stoykov
    • Proposed as answer by ivostoykov Monday, March 30, 2009 10:15 AM
    Monday, March 30, 2009 10:15 AM
  • Sorry for my mistake for not giving details about using the expression.

    I have a web form for creating User Login Account and have multiple fields like UserID , FirstName, LastName etc. I am using following validation controls for validing the value of UserID TextBox.

    <asp:RequiredFieldValidator ID="ReqF1" runat="server" ErrorMessage="Please choose a USER ID for the new account" Display="None" ControlToValidate="txtUserId" SetFocusOnError="True"></asp:RequiredFieldValidator>

    <asp:RegularExpressionValidator ID="RegExp1" runat="server" ErrorMessage="Special characters are not allowed in User ID field" Display="None" ControlToValidate="txtUserId"
    ValidationExpression="^([^_](\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)(\.)?)+[^_]$"
    SetFocusOnError="True"></asp:RegularExpressionValidator>

    This time I used your mentioned expression which is not allowing "_" as single and first and last character but also not allowing simple username as well like "testuser1".

    Please advice.

    Monday, March 30, 2009 10:33 AM
  • When you want to prevent a string beginning or ending with some kind of character, and that string could be a single character, then you need to use look-around.  Since you are using ASP RegularExpressionValidator, you are limited to the JavaScript/VBScript Regex syntax, but I believe this should work.  It rejects "_", "_joe", "joe_".  But it does not reject ".joe" or ".joe.", or "...".

    (?!^_.*$)(?!^.*_$)(^((\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+$)

     

     


    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Monday, March 30, 2009 11:33 AM
  • <div>
          <asp:TextBox ID="TextBox1" runat="server" CausesValidation="True"></asp:TextBox>
          <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" 
            ControlToValidate="TextBox1" ErrorMessage="RegularExpressionValidator" 
            ValidationExpression="^([^_](\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+[^_]$"></asp:RegularExpressionValidator>
        
        </div>
    The snippet above allows testuser1 and testuser1- but not _testuser1 or testuser1_
    HTH
    Ivo Stoykov
    HTH
    Ivo Stoykov
    • Proposed as answer by ivostoykov Monday, March 30, 2009 11:43 AM
    Monday, March 30, 2009 11:43 AM
  • But it does not allow for single letter user names.  That is because the pattern requires at least two characters.  It also allow invalid characters for the beginning and ending of a user name.  For example,

    "@$"

    ... would be valid with your expression.


    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Monday, March 30, 2009 12:30 PM
  • > "@$"
    this change the rule. Which characters are allowed and which are not? In your 1st post you've mentioned underscore only.
    if you;d like to disallow @# the rule must be re-written.

    following will exclude undescore as leading or lagging letter but will be acceptable into the name
    ^([^_]?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)[^_]?)$


    HTH
    Ivo Stoykov
    • Proposed as answer by ivostoykov Monday, March 30, 2009 1:01 PM
    Monday, March 30, 2009 1:01 PM
  • > "@$"
    This does not change the rule.  The original pattern did not allow these characters.  And a careful reading of the pattern suggests that the only valid characters are [a-zA-Z0-9_.-].  But, your proposed solution changes the rule by introducing additional characters that were not originally allowed.

    I may be wrong, but I don't believe that what VisioGuy was looking for.
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Monday, March 30, 2009 6:31 PM
  • Guys, following are the result of given expressions.

     

    Code Snippet Expression (Ivo Stoykov):

     

    ^([^_](\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+[^_]$

     

    Test Result:

    1- Does not allow single "_" as UserId as well beginning or ending of UserId as "_" character but accepts all special characters within username at any position like user#@ , user$$ etc

     

    Last Expression (Ivo Stoykov):

    ^([^_]?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)[^_]?)$

     

    Test Result:

    1- Allowing "_" only to use as UserId.

    2- Allowing "_" at beginning and ending of two letter words like "_ss" or "ss_" (not happening in more than two letters word).

     

    I think I should explain what I need.

     

    ^((\.)?([a-zA-Z0-9_-]?)(\.)?([a-zA-Z0-9_-]?)(\.)?)+$

     

    It is the original expression which needs to be re-written in such a way to disallow just single "_" as accepting userId value as well "_" at leading and trailing character of any word along with keeping all characteristics of the original expression (does not allow any special character in UserId).

    User ID can only: 
    - Have 1 to 30 character(s).
    - Have letters, numbers.
    - Have hyphen (-), underscore (_) and Periods (.).

    Tuesday, March 31, 2009 6:54 AM
  • User ID can only: 
    - Have 1 to 30 character(s).
    - Have letters, numbers.
    - Have hyphen (-), underscore (_) and Periods (.).

    Let me add some more definitions based on the previous posts.

    • Have not start with underscore (_)
    • Have not end with underscore (_)

    Need some more definitions about:

    1. What about hyphen(-) and Period(.). Whill thay be allowed at start/end of name?
    2. Will numbers be allowed at start/end of name?
    regards
    HTH
    Ivo Stoykov
    • Edited by ivostoykov Wednesday, April 01, 2009 7:01 AM some formating is not visible
    Wednesday, April 01, 2009 6:59 AM
  • Thanks Stoykov for viewing and adding more definitions. Let me summarize all of them:

    User ID can only: 

    - Have 1 to 30 character(s) length.
    - Any special character is not allowed at any position.
    - Have only combination of letters [a-z], [A-Z] , numbers [0-9] , hyphen (-), underscore (_) and Periods (.) 
    - Have not start with underscore (_)
    - Have not end with underscore (_)
    - Hyphen(-), Underscore (_) and Period(.) not be allowed at start/end of name.
    - Numbers are allowed at start/end of name.
    - User ID can be any single character that must be in the range of [a-z], [A-Z] or [0-9].

    Regards
    Wednesday, April 01, 2009 7:59 AM
  • VisioGuy,
    Please look at my earlier post.  It uses "look-around" to handle the your original requirements.  If you understand how "look-around" works, you can easily my modifications to it below.  I also limited it to 30 characters and changed the pattern to simplify.  Please note, the RegularExpressionValidator will not report an error if the control's text is empty (by control design), you must separately detect and reject blank usernames.

    Here's the updated pattern.

    (?!^[_.-].*$)(?!^.*[_.-]$)(^[a-zA-Z0-9_.-]{1,30}$)
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    • Marked as answer by VisioGuy Thursday, April 02, 2009 7:01 AM
    Wednesday, April 01, 2009 11:43 AM
  • Thanks a lot for both of you guys for getting your valuable time for viewing and providing the solution. Now it is working PERFECT!
    Thursday, April 02, 2009 7:03 AM
  • I think people are looking too much into this.  It is actually a very simple regex.

    ^([A-Za-z0-9]+)([A-Za-z0-9_]*)([A-Za-z0-9]+)$

    This matches:

    Zebra
    89Zebra
    Zeb_ra
    Zebra56
    Z_A

    but not:

    _
    _Zebra
    Zebra_
    _Ze_bra_


    I didn't add "-" into the character class, if you want to match that, I figured you can just throw it in there.  You can throw any other characters in there as well that you want to validate at the beginning or end.  Using the anchors ^ $ to check the beginning and the end does pretty much everything that you need.  using "+" on the first character class accepts 1 more of the class.  The second character class uses "*" and accepts 0 or more of whatever.  And the last does the same as the first only anchored at the end. 
    Sunday, April 05, 2009 2:46 PM
  • Kevin,
    Your simple expression is flawed and will fail for certain valid terms (according to the requirements).  Please read the entire thread, then write a complete set of test cases and see which ones fail.  If your sample set exercise all the requirements, you will find the failure.  You are correct, too much has been said about this, so I'll leave the proof as an exercise to the reader.
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Tuesday, April 07, 2009 12:48 AM
  • User ID can only: 

    1 Have 1 to 30 character(s) length.
    2 Any special character is not allowed at any position.
    3 Have only combination of letters [a-z], [A-Z] , numbers [0-9] , hyphen (-), underscore (_) and Periods (.) 
    4 Have not start with underscore (_)
    5 Have not end with underscore (_)
    6 Hyphen(-), Underscore (_) and Period(.) not be allowed at start/end of name.
    7 Numbers are allowed at start/end of name.
    8 User ID can be any single character that must be in the range of [a-z], [A-Z] or [0-9].

    I'm not sure what you mean.  The only requirement I really did not meet is the character length.  That can be tested separately if needed.  Here is an updated regex to include the 'special character cases' I left out. 

    ^([A-Za-z0-9]+)([A-Za-z0-9_\-.]*)([A-Za-z0-9]+)$

    As I mentioned previously, I did not match length.  I am not quite sure how to do that with a regex and I'm trying to understand how yours works.  You say it uses 'lookaround'.  I familiar with perl's positive/negative lookahead and lookbehind but not a 'lookaround'.  I'm just trying to convert between both and seeing what works where.  I would like to understand how your pattern matches length.




    Saturday, April 11, 2009 1:17 PM
  • Your script allows 2-30 characters, not 1-30.  The reason is that you have a construct that requires a beginning and an ending character.

    1 character usernames can be tested separately, but not when using RegularExpressionValidator.  To use a separate test, RegularExpressionValidator must accept at least all valid combinations.

    But, you could take your expression and add an OR to the expression to accept the 1 character username.  That would be simpler than using look-around.

    To understand my look-around expression, look at it as 3 expressions AND-ed together.

    1.  (?!^[_.-].*$)  allow any string as long as it does not begin with '_', '.', or '-' (underscore, dot, or hypen)
    2.  (?!^.*[_.-]$)  allow any string as long as it does not end with the same.
    3.  (?=^[a-zA-Z0-9_.-]{1,30}$)  allow a 1-30 character string containing the allowed characters

    By AND-ing these (AND requires that all but one expression is a look-around), the first two expressions eliminate the 3 invalid possibilities that the 3rd expression allows.


    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Monday, April 13, 2009 6:54 PM
  • Thanks for breaking that down for me.  I understand what is going on and why mine matches at minimum 2 instead of 1.  I didn't even notice that.  I really wasn't testing for length anyways, I would have explicitly tested for length with a conditional.  But I guess your regex is a cooler way to do it.
    Friday, April 17, 2009 8:23 PM