4

我正在寻找一个像样的正则表达式来匹配一个 URL(带有方案、域、路径等的完整 URL)我通常会使用 filter_var 但在这种情况下我不能,因为我必须支持 PHP<5.2!

我在网上搜索过,但找不到任何我确信会万无一失的东西,而且我能在 SO 上找到的只是人们说要使用 filter_var。

有人有用于此的正则表达式吗?

我的代码(这样你就可以看到我想要实现的目标):

function validate_url($url){
    if (function_exists('filter_var')){
        return filter_var($url, FILTER_VALIDATE_URL);
        }
    return preg_match(REGEX_HERE, $url);
    }
4

4 回答 4

2

我创建了一个用于验证域的解决方案。虽然它没有具体涵盖整个 URL,但它非常详细和具体。您需要问自己的问题是,“我为什么要验证域?” 如果要查看域是否真的存在,则需要确认域(包括有效的 TLD)。问题是,太多的开发人员走捷径 ([az]{2,4}) 并称其为好。如果您按照这些思路思考,那么为什么称其为 URL 验证呢?它不是。它只是通过正则表达式传递 URL。

我有一个开源类,它不仅允许您使用单一来源的 TLD 管理 (iana.org) 来验证域,而且还可以通过 DNS 记录验证域以确保它确实存在。DNS 验证是可选的,但域将根据 TLD 明确有效。

例如:example.ay 不是有效域,因为 .ay 顶级域名无效。但是使用此处发布的正则表达式 ([az]{2,4}),它会通过。我对质量有亲和力。我尝试在我编写的代码中表达这一点。其他人可能并不真正关心。因此,如果您想简单地“检查” URL,您可以使用这些响应中列出的示例。如果您真的想验证 URL 中的域,您可以在我创建的类中执行此操作。它可以在以下位置下载: http ://code.google.com/p/blogchuck/source/browse/trunk/domains.php

它基于“管理”(松散地使用该术语)确定有效域的内容的 RFC 进行验证。简而言之,域类将执行以下操作:域验证的基本规则

  • 必须至少有一个字符长
  • 必须以字母或数字开头
  • 包含字母、数字和连字符
  • 必须以字母或数字结尾
  • 可能包含多个节点(即node1.node2.node3)
  • 每个节点最多只能有 63 个字符
  • 总域名最多只能包含 255 个字符
  • 必须以有效的 TLD 结尾
  • 可以是 IP4 地址

只有在检查您的本地副本后,它才会下载主 TLD 文件 iana.org 的副本。如果您的本地副本已过期 30 天,它将下载一个新副本。文件中的 TLD 将在 REGEX 中用于验证您正在验证的域中的 TLD。这可以防止 .ay(和其他无效 TLD)通过验证。

这是一段很长的代码,但考虑到它的作用,它非常紧凑。而且是最准确的。这就是我之前问这个问题的原因。你想做“验证”还是简单的“检查”?

于 2010-03-06T03:50:01.443 回答
1

我见过一个正则表达式,它实际上可以验证任何类型的有效 URL,但它有两页长......

您最好解析 url,parse_url然后检查所有必需的位是否按顺序排列。

补充: 这是我的 URL 类的一个片段:

public static function IsUrl($test)
{
    if (strpos($test, ' ') > -1)
    {
        return false;
    }
    if (strpos($test, '.') > 1)
    {
        $check = @parse_url($test);
        return is_array($check)
            && isset($check['scheme'])
            && isset($check['host']) && count(explode('.', $check['host'])) > 1
}
    return false;
}

它测试给定的字符串并需要 url 中的一些基础知识,即设置方案并且主机名中有一个点。

于 2010-03-05T22:11:59.960 回答
1
!(https?://)?([-_a-z0-9]+\.)*([-_a-z0-9]+)\.([a-z]{2,4})(/?)(.*)!i

我使用这个正则表达式来验证 URL。到目前为止,它一次都没有让我失望:)

于 2010-03-05T22:12:26.870 回答
1

你可以试试这个。我自己没有尝试过,但它肯定是我见过的最大的正则表达式,哈哈。

^(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$
于 2010-03-05T22:12:53.733 回答