0

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

规则很简单:

  • 第一个字符必须是字母
  • 他们也可以使用数字,但这不是第一个
  • 他们可以使用一次句号/下划线,但不能在用户名末尾使用

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

20 分钟后添加:

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

4

4 回答 4

5

拿你描述的部分:

  • 第一个字符必须是字母

开始^[A-Za-z]

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

[A-Za-z0-9]*在中间

  • 他们可以使用一次句号/下划线,但不能在用户名末尾使用

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

把它们放在一起,你就有了:/^[A-Za-z][A-Za-z0-9]*([._][A-Za-z0-9]+)?$/. 使用不区分大小写 '/i' 的标志可以让您删除 'AZ': /^[a-z][a-z0-9]*([._][a-z0-9]+)?$/i

正则表达式等价于确定性有限自动机(DFA)。研究它们可以帮助掌握正则表达式。特别是状态之间的转换,直接适用于你的三点。这种语言的(简化的)状态图应该很容易理解: /^[az][a-z0-9]*([._][a-z0-9])的状态图?/

外交部:

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

我称它为“减少”,因为有第五个不接受状态和未显示的导致它的边缘。基本上,如果遇到的字符不是列出的字符,DFA 就会转换到第五个不接受状态并停留在那里。

于 2013-08-12T03:11:42.640 回答
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 的回答。

于 2013-08-12T03:11:08.280 回答
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

关于“愚蠢的用户名”,除了编写“黑名单”并在之后(或在具有前瞻或后视的模式中)检查用户名之外,您无能为力,但我不确定这是否非常有用,因为它不是密码。

于 2013-08-12T03:34:26.710 回答
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;
}
于 2013-08-12T03:49:19.317 回答