如何在PHP中“合并”这两个正则表达式?

时间:2012-09-14 17:51:18

标签: php regex preg-match username

我正在学习正则表达,所以请跟我一起轻松!

不以_ (下划线)开头,并且如果仅包含字词(字母,数字和下划线本身)时,用户名被视为有效:< / p>

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 个答案:

答案 0 :(得分:5)

您可以在第二个正则表达式中添加否定先行断言:

^(?!_)\w+$

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

See it work

答案 1 :(得分:1)

问题是De Morgan's Law^_+[^\w]+$仅在以一个或多个下划线开头 所有后续字符为非单词字符时才会匹配。如果它以下划线 开头,则需要匹配任何字符都是非单词字符。

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

if (! preg_match('/^[^\W_]\w*$/', $value, $matches)) {

答案 2 :(得分:1)

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

[\w\d_]+部分与锚点(^和$)相结合,实质上断言整个字符串只包含那些字符。 (?!_)部分是负前瞻断言。这意味着检查下一个字符不是下划线。由于它位于^锚旁边,因此可确保第一个字符不是下划线。

答案 3 :(得分:0)

简单的解决方案就是:

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

您只需要\w组(包括下划线)但没有下划线,因此[a-zA-Z0-9]相当于\w但没有下划线。