我正在使用正则表达式来验证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;
}
}
我对正则表达式不是很擅长,所以我无法弄清楚这个问题,请帮我纠正正则表达式。
答案 0 :(得分:6)
哇,这是一个很大的表达。我发现了几个错误,我希望能向你解释。让我们分开吧:
$pattern ="/
这是你的第一个错误。由于正斜杠用于URL的多个部分,因此应使用不同的分隔符。我建议使用代字号~
,因为这不常用于网址。这意味着您不必在\/
的每个位置都保持转义正斜杠。
^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+
此字符类包含下一个错误。在字符类中,点只表示一个点。没有必要逃脱它。此外,将仪表放在末端,它也不需要转义,因为它不可能意味着范围。字符类可以缩短为[a-zA-Z0-9.-]+
。
(\:[a-zA-Z0-9\.&%\$\-]+
这里我们在字符类中有下一个错误&
。这将匹配&或a或a或m或a;,而不仅仅是&amp ;.您不需要将其转换为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.,?'\\+&%$#=\~_-]+))*$~";
现在您的表达式较小,找到错误和更多自定义应该会更容易一些。
只是快速说明
我一直注意到您在某些分组的开头(\:
使用了以下语法。我删除了反斜杠,因为它不需要冒号。但是,你是否试图让它成为未被捕获的群体?如果是这样,那么语法是(?:
。
编辑:: 您还可以通过使用字符类
进一步优化模式 \ 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";
答案 1 :(得分:1)
我看到一个错误:
[0-9]+)*(/($
到
[0-9]+)*(\/($
或
[0-9]+)*(($
如果/
应该是一个ender,它不应该是。
但严重的是,你有没有办法实现这一目标?这个字符串很难排除故障。
答案 2 :(得分:0)
为什么不使用标准的php函数filter_var?