正则表达式验证URL在PHP中无法正常工作

Kan*_*iya 1 php regex codeigniter

我正在使用正则表达式来验证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
Run Code Online (Sandbox Code Playgroud)

这是我的表达

$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\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";
Run Code Online (Sandbox Code Playgroud)

这是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;
    }       
}
Run Code Online (Sandbox Code Playgroud)

我不是很擅长正则表达式,所以我无法弄清楚问题,请帮我纠正正则表达式.

joe*_*e92 6

哇,这是一个很大的表达.我发现了几个错误,我希望能向你解释.让我们分开吧:

$pattern ="/
Run Code Online (Sandbox Code Playgroud)

这是你的第一个错误.由于正斜杠用于URL的多个部分,因此应使用不同的分隔符.我建议使用代字号~,因为这不常用于网址.这意味着你不必一直在逃避正斜杠\/.

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

此字符类包含下一个错误.在字符类中,点只表示一个点.没有必要逃脱它.此外,将仪表放在末端,它也不需要转义,因为它不可能意味着范围.字符类可以缩短成为[a-zA-Z0-9.-]+.

(\:[a-zA-Z0-9\.&%\$\-]+
Run Code Online (Sandbox Code Playgroud)

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

)*@)*(\.){1}
Run Code Online (Sandbox Code Playgroud)

部分原因可能是错误,也可能不是.基本上,有没有必要在这里捕捉点?如果不需要捕获它,请单独留下支架.但是,重复中存在明确的错误.{1}是完全绝对多余的.那里的一切都必须至少重复一次.这只是让代码变得混乱.以上可以缩短为,)*@)*\..

((25[0-5]|2[0-4][0-9]|[0-1]{1}
Run Code Online (Sandbox Code Playgroud)

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

[0-9]{2}|[1-9]{1}[0-9]{1}
Run Code Online (Sandbox Code Playgroud)

再次两次,这变成了[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])
Run Code Online (Sandbox Code Playgroud)

|[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])
Run Code Online (Sandbox Code Playgroud)

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

|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+
Run Code Online (Sandbox Code Playgroud)

可以优化两个字符类|([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})
Run Code Online (Sandbox Code Playgroud)

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

)(\:[0-9]+)*(/
Run Code Online (Sandbox Code Playgroud)

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

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

知道我们不需要逃避其中的所有内容,因此可以大大缩短该角色类.它可以变成,($|[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.,?'\\+&%$#=\~_-]+))*$~";
Run Code Online (Sandbox Code Playgroud)

既然你有一个较小的表达式,找到错误和更多的自定义应该会更容易一些.

只是一个快速的说明
我一直注意到你在一些分组的开头使用了以下语法,(\:.我删除了反斜杠,因为它不需要冒号.但是,你是否试图让它成为未被捕获的群体?如果是这样,那么语法是,(?:.

编辑:: 您还可以通过使用字符类进一步优化模式

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

将i添加到最后一个模式分隔符的末尾也会导致不区分大小写.这意味着,而不是写作,[a-zA-Z]你可以只写[a-z].

而且,http|https可以成为https?

所以你的模式也可以进一步缩短:

$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";
Run Code Online (Sandbox Code Playgroud)