4

我正在学习正则表达式,所以请放轻松!

如果用户名不以_(下划线)开头并且仅包含单词字符(字母、数字和下划线本身),则认为用户名有效:

namespace Gremo\ExtraValidationBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UsernameValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint)
    {
        // Violation if username starts with underscore
        if (preg_match('/^_', $value, $matches)) {
            $this->context->addViolation($constraint->message);
            return;
        }

        // Violation if username does not contain all word characters
        if (!preg_match('/^\w+$/', $value, $matches)) {
            $this->context->addViolation($constraint->message);
        }
    }
}

为了将它们合并到一个正则表达式中,我尝试了以下方法:

^_+[^\w]+$

解读为:如果以下划线开头(最终不止一个),并且如果后面至少有一个字符是不允许的(不是字母、数字或下划线),则添加违规。例如,不适用于“_test”。

你能帮我理解我错在哪里吗?

4

4 回答 4

5

您可以在第二个正则表达式中添加一个否定的前瞻断言:

^(?!_)\w+$

这意味着,尝试匹配整个字符串,而不是它的任何部分。字符串不能以下划线开头,并且可以包含一个或多个单词字符。

看它工作

于 2012-09-14T17:56:25.267 回答
1

问题是德摩根定律仅当它以一个或多个下划线开头并且所有后续字符都是非单词字符^_+[^\w]+$时才会匹配。如果它以下划线开头任何字符是非单词字符,则需要匹配。

我认为在这种情况下,关注有效的用户名更简单:它们以非下划线的单词字符开头,所有剩余的字符都是单词字符。换句话说,有效的用户名由模式描述^[^\W_]\w*$。所以,你可以写:

if (! preg_match('/^[^\W_]\w*$/', $value, $matches)) {
于 2012-09-14T17:57:03.317 回答
0

简单的解决方案是这样的:

if (!preg_match('/^[a-zA-Z0-9]+$/', $value, $matches)) {

你只想要\w组(包括下划线)但没有下划线,所以[a-zA-Z0-9]相当于\w但没有下划线。

于 2012-09-14T17:59:12.090 回答
0

当然,有许多不同的方法可以做到这一点。我可能会考虑使用类似的东西/^(?!_)[\w\d_]+/$

与锚(^ 和 $)结合的[\w\d_]+部分基本上断言整个字符串仅由这些字符组成。(?!_) 部分是一个否定的前瞻断言。这意味着检查下一个字符不是下划线。由于它就在 ^ 锚旁边,因此可以确保第一个字符不是下划线。

于 2012-09-14T17:59:20.760 回答