?
Solved

Regex to allow only letter, number and underscores

Posted on 2014-08-05
12
Medium Priority
?
714 Views
Last Modified: 2014-08-06
Hi,

im curious if it is possible to allow users to create a username with only letters numbers and underscores. the underscores cannot be back to back either

thanks in advance
0
Comment
Question by:J N
  • 4
  • 4
  • 4
12 Comments
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40241814
Yes, it can be done.  It might be easier to use a couple of expressions instead of trying to do this all in one REGEX.
http://xkcd.com/1171/
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40241844
Please see http://iconoun.com/demo/temp_jaymenagy.php

<?php // demo/temp_jaymenagy.php
ini_set('display_errors', TRUE);
error_reporting(E_ALL);

// SEE http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28491049.html

function validate_password($pwd)
{
    $rgx
    = '/'      // REGREX DELIMITER
    . '['      // CHARACTER CLASS
    . '^'      // NEGATION - MATCH ANYTHING THAT IS NOT ONE OF THIS CLASS
    . 'A-Z'    // LETTERS
    . '0-9'    // NUMBERS
    . '_'      // UNDERSCORE
    . ']'      // END CHARACTER CLASS
    . '/'      // REGREX DELIMITER
    . 'i'      // CASE-INSENSITIVE
    ;
    if (preg_match($rgx, $pwd)) return FALSE;
    if (strpos($pwd, '__') === FALSE) return TRUE;
    return FALSE;
}

$dat = array
( 'abc123'
, 'abc123*'
, 'abc_123'
, 'abc__123'
)
;

foreach ($dat as $pwd)
{
    echo PHP_EOL . "<br>$pwd ";
    $sig = validate_password($pwd);
    if ($sig) echo "OK";
        else echo "FAIL";
}

Open in new window

Ed. note: Changed line 21 to use === instead of == comparison.
0
 
LVL 35

Expert Comment

by:Dan Craciun
ID: 40242142
Here's a pure regexp solution, enforcing a minimum length too:
'/^(?!.*__).*\w{6}?$/im'

Open in new window

Replace 6 with how many characters you want your passwords to have.

PS @Ray: instead of [^A-Z0-9_] you can simply say \W

HTH,
Dan
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Author Comment

by:J N
ID: 40242161
Hi

it is possible to ensure that there are not only numbers?

in Ray's example '12352' would pass
0
 
LVL 35

Expert Comment

by:Dan Craciun
ID: 40242167
Yup. Lookaheads are your friends:
'/^(?!.*__)(?=.*[A-Z]).*\w{6}?$/im'

Open in new window

0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40242376
Are there any other requirements you want to add to the question?  For example, some of the common requirements for passwords demand that they start with a letter and have at least one upper, one lower, one special, one number and contain no natural language words, etc.  The more detailed you can make the rule set, the more likely you will get the best answer.
0
 
LVL 6

Author Comment

by:J N
ID: 40242395
Its not for a password its for usernames

i want to limit the ability to only accept particular charteres as i use - and .  to denote spaces in system processes.

i do not want a user name:
  - of only number
 - only underscores
  - number and underscores

i think having it start with letters is the best

ex :

 jaymenagy
jayme_nagy
j_nagy123

all are desirable
0
 
LVL 35

Expert Comment

by:Dan Craciun
ID: 40242402
'/^[A-Z](?!.*__).*\w{5}?$/im'

Open in new window

Starts with a letter, does not have consecutive _, accepts only letters, numbers and _, at least 6 characters.
0
 
LVL 6

Author Comment

by:J N
ID: 40242405
using rays code

function validate_password($pwd)
{
    $rgx
    = '/^[A-Z](?!.*__).*\w{5}?$/im';    
    ;
    if (preg_match($rgx, $pwd)) return FALSE;
    if (strpos($pwd, '__') === FALSE) return TRUE;
    return FALSE;
}

$dat = array
( 'abc123'
, 'abc123*'
, 'abc_123'
, 'abc__123'
, '12553'
)
;

foreach ($dat as $pwd)
{
    echo PHP_EOL . "<br>$pwd ";
    $sig = validate_password($pwd);
    if ($sig) echo "OK";
        else echo "FAIL";
}

Open in new window


i get

<br>abc123 FAIL
<br>abc123* OK
<br>abc_123 FAIL
<br>abc__123 FAIL
<br>12553 OK
0
 
LVL 35

Assisted Solution

by:Dan Craciun
Dan Craciun earned 1000 total points
ID: 40242411
Yup. The results are inverse. Ray's code tested for failures, my expression is used to test for valid values.
$dat = array
( 'abc123'
, 'abc123*'
, 'abc_123'
, 'abc__123'
, '12553'
)
;
$rgx = '/^[A-Z](?!.*__).*\w{5}?$/im';
foreach ($dat as $pwd)
{
    echo PHP_EOL . "<br>$pwd ";
     if (preg_match($rgx, $pwd)) echo "OK";
          else echo "FAIL";
}

Open in new window

0
 
LVL 111

Accepted Solution

by:
Ray Paseur earned 1000 total points
ID: 40244805
As I see programmers sometimes struggle to understand complex and advanced concepts like regular expressions, I am more and more inclined to write a bit more code with comments that explain my thinking.  Strategy: Comment the "why" not the "what."  This code sample seems to implement the current iteration of the expressed rules, and it's not intended to be a criticism or contradiction of Dan's take on the problem.  Regex is a language unto itself, and since it's almost 100% made up of punctuation, it is very difficult to explain regex in natural language.  So I lean in the direction of simplifying and deconstructing the problem into parts that are easy to explain and easy to test.

<?php // demo/temp_jaymenagy.php
ini_set('display_errors', TRUE);
error_reporting(E_ALL);

// SEE http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28491049.html

/**
 * Canonical Rules:
 *
 * Starts with a letter
 * May have only letters, numbers and underscores
 * May not have consecutive underscores
 *
 * Side-Effect Rules
 *
 * May not start with an underscore
 * May not be all numbers
 * May not be only numbers and underscores
 */
function validate_password($pwd)
{
    // ISOLATE THE FIRST CHARACTER
    $pwd = trim($pwd);
    $pwd_start = substr($pwd,0,1);

    // STARTS WITH A LETTER
    $rgx_starts_letter
    = '/'          // REGEX DELIMITER
    . '[A-Z]'      // CHARACTER CLASS OF LETTERS
    . '/'          // REGEX DELIMITER
    . 'i';         // CASE-INSENSITIVE
    ;
    if (!preg_match($rgx_starts_letter, $pwd_start)) return FALSE;

    // NOTHING BUT LETTERS, NUMBERS, UNDERSCORES
    $rgx_bad_characters
    = '/'          // REGEX DELIMITER
    . '[^A-Z0-9_]' // CHARACTER CLASS OF EVERYTHING THAT IS NOT LETTER, NUMBER, UNDERSCORE
    . '/'          // REGEX DELIMITER
    . 'i';         // CASE-INSENSITIVE
    ;
    if (preg_match($rgx_bad_characters, $pwd)) return FALSE;

    // NO CONSECUTIVE UNDERSCORES
    if (strpos($pwd, '__') !== FALSE) return FALSE;

    // ALL TESTS PASSED
    return TRUE;
}

$dat = array
( 'abc123'
, 'abc123*'
, 'abc_123'
, 'abc__123'
, '123_abc'
, '123456'
, '1_2_3'
, 'a_1_2_3_'
, 'a_1_2_3__'
, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
)
;

foreach ($dat as $pwd)
{
    echo PHP_EOL . "<br>$pwd ";
    $sig = validate_password($pwd);
    if ($sig) echo "OK";
        else echo "FAIL";
}

Open in new window

0
 
LVL 6

Author Closing Comment

by:J N
ID: 40244890
Thanks guys !!!! big help

Regex is confusing as hell so i like the approach of taking it apart
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.
Suggested Courses
Course of the Month16 days, 20 hours left to enroll

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question