PHP正则表达式允许特定的用户名

时间:2013-08-12 03:06:32

标签: php regex

这是我的第一个问题。目前我正在开发一个PHP论坛脚本,我想让人们注册一个遵守我的规则的用户名。

规则很简单:

  • 第一个字必须是一个字母
  • 他们也可以使用数字,但它不是第一个
  • 他们可以使用fullstop / underscore一次但不能在用户名结尾处使用

请放下功能帮助我。我读了一些教程,但不太了解正则表达式。因此我被困住了。提前感谢您的回答。

20分钟后添加:

感谢您的回答,我还有一件事要问,我可以解除愚蠢的用户名吗?例如。 aaa123,ab-cd,uuuu ......比怎么样?

4 个答案:

答案 0 :(得分:5)

拿你描述的部分:

  
      
  • 第一个字必须是一个字母
  •   

它开始^[A-Za-z]

  
      
  • 他们也可以使用数字,但它不是第一个
  •   

[A-Za-z0-9]*位于中间

  
      
  • 他们可以使用fullstop / underscore一次但不能在用户名结尾处使用
  •   

可选地,有一个下划线,后跟至少一个其他有效字符([._][A-Za-z]+)?

把它们放在一起,你有:/^[A-Za-z][A-Za-z0-9]*([._][A-Za-z0-9]+)?$/。使用案例'/ i'不敏感标记可以删除'A-Z':/^[a-z][a-z0-9]*([._][a-z0-9]+)?$/i

正则表达式相当于deterministic finite automatons(DFA)。研究它们有助于掌握正则表达式。特别是,州之间的过渡直接适用于您的三点。这种语言的(简化)状态图应该很容易理解: State diagram for /^[a-z][a-z0-9]*([._][a-z0-9])?/

DFA:

  • 从州0开始
  • 如果遇到字母,
  • 转换到状态1,
  • 只要遇到字母和数字,
  • 就会处于状态1,
  • 如果遇到句点或下划线,则切换到状态2,
  • 如果遇到字母和数字,则切换到状态3,
  • 只要遇到字母和数字,
  • 就会处于状态3,
  • 接受字符串,如果它以状态1或3结束

我把它称为“缩小”,因为有第五个不接受的状态和导致它的边缘未显示。基本上,如果遇到的字符不是列出的字符,则DFA会转换到第五个不接受的状态并保持不变。

答案 1 :(得分:1)

preg_match与正则表达式^[a-z][a-z0-9]*([._][a-z0-9]+)?$一起使用:

$regex = '/^[a-z][a-z0-9]*([._][a-z0-9]+)?$/i';
echo preg_match($regex, 'valid_user1'); # => 1
echo preg_match($regex, 'Valid_user1'); # => 1
echo preg_match($regex, '0invalid_user'); # => 0
echo preg_match($regex, 'invaliduser_'); # => 0
echo preg_match($regex, 'in_valid_user'); # => 0

<强>更新

正则表达来自outis的答案。

答案 2 :(得分:0)

以下模式允许4到12个字符之间的用户名,字母为第一个字符,只有一个点,只有一个下划线:

$pattern = '~^(?=.{4,12}$)[a-z]++[^\W_]*+(_[^\W_]++)?+(?>\.[^\W_]++)?+(?(1)|(_[^\W_]++)?+)$~i';

您可以将它与preg_match一起使用来检查用户名。

模式详情

~                # pattern delimiter
^                # begining anchor
(?=.{4,12}$)     # lookahead assertion: check if the length is between 4 and 12
                 # characters. It stand for: "followed by between 4 and 12 chars
                 # and the end of the string
[a-z]++          # one or more letters
[^\W_]*+         # zero or more letters or digits. Since ^ means that the character
                 # class is negated, _ is excluded with all that is not a part of \w
(_[^\W_]++)?+    # first capturing group with an underscore and one or more
                 # letters/digits. The group is optional
(?>\.[^\W_]++)?+ # a non capturing group with a dot (optional too)
(?(1)            # conditional: if the first capturing group exist there is nothing
     |           # OR
   (_[^\W_]++)?+ # you can have an underscore here (optional)
)
$                # anchor: end of the string
~                # pattern delimiter
i                # case insensitive modifier

关于“dumb用户名”除了写一个“黑名单”并检查用户名之后(或者在带有前瞻或后瞻的模式中),你做不了多少但是我不确定这会非常有用,因为它不是密码。

答案 3 :(得分:0)

我知道你要求一个正则表达式,但也许我可以说服你,它可以很容易地用老式的方式完成:

function validUsername($user) {

    // A few variables
    $minlen = 3;
    $maxlen = 20;
    $usrlen = strlen($user);

    // Allowed length of username
    if ($usrlen < $minlen || $usrlen > $maxlen) {
        return false;
    }
    // First character must be alpha
    if ( ! ctype_alpha($user[0])) {
        return false;
    }
    // Last letter cannot be . or _ which means
    // that it must be alphanum
    if ( ! ctype_alnum($user[$usrlen-1])) {
        return false;
    }
    // Go over each character, excluding the first
    // and last, because we have already dealt with them
    for ($i = 1; $i < $usrlen-1; $i++) {

        // Grab the currect character
        $char = $user[$i];

        // If it is alphanum then it is valid
        if (ctype_alnum($char)) {
            continue;
        }
        // Dots and underscores cannot appear in pairs
        elseif ($char === '.' || $char === '_') {
            if ($user[$i-1] === $char || $user[$i+1] === $char) {
                return false;
            }
        }
        // Character not supported
        else return false;
    }
    // Everything seems to be in order
    return true;
}