1

我正在使用正则表达式来验证 URL。这个表达式在 JavaScript 中效果很好,但是在 PHP 中它给了我这个错误

A PHP Error was encountered

Severity: Warning

Message: preg_match() [function.preg-match]: Unknown modifier '('

Filename: home/auth.php

Line Number: 1596
A PHP Error was encountered

Severity: Warning

Message: preg_match() [function.preg-match]: Unknown modifier '('

Filename: home/auth.php

Line Number: 1601

这是我的表达

$pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";

这是php函数

public function valid_url($data)
{
    $data = trim($data);

    if(!$data)
    {
        return TRUE;            
    }

    $pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";
    $valid = preg_match($pattern,$data);

    if(!$valid)
    {
        $data = "http://".$data;
        $valid = preg_match($pattern,$data);
    }

    if(!$valid)
    {
        $this->form_validation->set_message('valid_url', 'Please enter a valid URL.');
        return FALSE;           
    }
    else
    {
        return TRUE;
    }       
}

我不太擅长正则表达式,所以我无法弄清楚问题所在,请帮助我更正正则表达式。

4

3 回答 3

6

哇,好大的表情。我在其中发现了几个错误,希望能向您解释。让我们把它分开:

$pattern ="/

这是你的第一个错误。由于在 url 的多个部分中使用了正斜杠,因此您应该使用不同的分隔符。我建议使用波浪号~,因为它不经常在 url 中使用。这意味着您不必在任何地方都使用\/.

^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+

这个字符类包含下一个错误。在字符类中,点仅表示点。没有必要逃避它。此外,将破折号放在最后,它也不需要转义,因为它不可能表示范围。字符类可以缩短为[a-zA-Z0-9.-]+.

(\:[a-zA-Z0-9\.&%\$\-]+

这里我们有下一个错误,&在字符类中。这将匹配 & 或 a 或 m 或 ;,而不仅仅是 &。您不需要将其转换为 html 代码,因为这样做意味着匹配代码包含的任何字符。并且使用以前的知识,您不需要转义点,或者如果它在末尾,则不需要转义。您也不需要转义美元符号,因为在字符类中它仅表示一美元。请记住,在字符类中,所有元字符都只是标准字符,除了插入符号^、反斜杠\、右方括号]、破折号-(但如果它位于末尾,则可以保留)以及您选择的任何分隔符,例如波浪~号 然后这个字符类可以变成[a-zA-Z0-9.&%$-]+.

)*@)*(\.){1}

其中一部分可能是错误,也可能不是。基本上,有没有必要在这里捕捉点?如果不需要捕获它,请单独留下括号。但是,重复有一个明确的错误。{1}完全是多余的。那里的一切都必须至少重复一次。这只是使代码混乱。以上可以简写为,)*@)*\.

((25[0-5]|2[0-4][0-9]|[0-1]{1}

同样,{1}不需要。删除它,((25[0-5]|2[0-4][0-9]|[0-1]

[0-9]{2}|[1-9]{1}[0-9]{1}

再两次,这变成了[0-9]{2}|[1-9][0-9]
你继续这样做,你的下一个代码块可以缩短:

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])

进入

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])

它并没有好得惊人,但每一点都有帮助。下一个:

|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+

这两个字符类可以优化,|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+.

\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2})

这是非常严格的,但我认为你有这样的原因是有原因的,所以我会离开它。

)(\:[0-9]+)*(/

这是您错误的原因。你没有逃脱正斜杠。但是,我将保留它,因为使用不同的分隔符可以避免这种情况并整理您的模式。

($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";

现在知道我们不需要转义其中的所有内容,该角色类可以大大缩短。它可以变成,($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/";.

使用我们现在知道的一切,你的模式可以变得更漂亮,更容易处理。

它可以变成:

$pattern = "~^(http|https|ftp)://www\.([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])|([a-zA-Z0-9-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(/($|[a-zA-Z0-9.,?'\\+&%$#=\~_-]+))*$~";

现在您有了一个更小的表达式,查找故障和更多的自定义应该会更容易一些。

Just a quick note
I keep noticing that you have used the following syntax at the beginning of some groupings, (\:. I have removed the backslash as it is not needed for a colon. However, were you trying to make it so the group was not captured? If so, the syntax for that is, (?:.

Edit:: You can also optimize the pattern further by utilizing character classes

\d = [0-9]
\w = [a-zA-Z0-9_]

Adding i to the end of the last pattern delimiter turns case insensitivity on too. Which means, instead of writing [a-zA-Z] you can just write [a-z] instead.

Also, the http|https can just become https?

So you pattern could be shortened further too:

$pattern = "~^(https?|ftp)://www\.([a-z\d.-]+(:[a-z\d.&%$-]+)*@)*((25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9])\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|\d)|([a-z\d-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-z]{2}))(:\d+)*(/($|[\w.,?'\\+&%$#=\~-]+))*$~i";
于 2012-04-24T12:09:30.157 回答
1

我看到一个错误:

[0-9]+)*(/($

[0-9]+)*(\/($

或者

[0-9]+)*(($

如果/应该是一个终结者,它不应该是。

但是说真的,没有其他方法可以实现这一目标吗?这个字符串真的很难排除故障。

于 2012-04-24T11:35:49.380 回答
0

为什么不使用标准的 php 函数 filter_var?

http://lv.php.net/manual/ru/function.filter-var.php

于 2012-04-24T11:30:52.843 回答