【问题标题】:PHP regex for validating a URL用于验证 URL 的 PHP 正则表达式
【发布时间】:2010-03-05 22:06:19
【问题描述】:

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

我在网上搜索过,但找不到任何我确信会万无一失的东西,我只能在 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);
    }

【问题讨论】:

  • URI 验证可能有上千种不同的正则表达式。你应该选择哪一个取决于你想要它(或需要它)的严格程度和精确程度。鉴于 URI 语法随着新增内容(例如非 ASCII URI)而变得更加复杂,因此可能无法尊重标准中的所有内容进行验证。但无论如何,选择一个:regexlib.com/…
  • 你可以考虑试试php.net/parse_url
  • @Frank:“这个函数不是用来验证给定的 URL”...
  • @poke 我正在查看您提供的列表(顺便说一下,有一些优点)。 @Frank 虽然 parse_url 确实允许您验证 URL,但这不是它的预期行为(如 poke 所说)。我只是猜测,但它可能会占用大量资源。

标签: php regex validation url backwards-compatibility


【解决方案1】:

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

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

例如:example.ay 不是有效域,因为 .ay 顶级域名无效。但是使用此处发布的正则表达式([a-z]{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)通过验证。

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

【讨论】:

  • 您的解决方案非常全面,但对于我想要实现的目标来说可能有点矫枉过正!我完全同意,对于完整的域验证,TLD 应该是现有的,但我很高兴它不是。请随意告诉我,但我真正需要知道的是用户输入了一些看起来像 URL 的东西,而不是输入相对地址、电子邮件地址或用户在被要求时可能输入的任何其他奇怪数据一个网址!
  • 不用担心。再次,这就是我问的原因,你真的在​​寻找“验证”还是只是“检查”。我看你想要后者。所以提供的其他解决方案应该足够了。至于告诉你,这不是这些类型的网站的用途。生命太短暂,不能那么激进。你知道你想要什么比我知道你想要什么还要多。 ;) 无论如何,祝你的项目好运,编码愉快!
  • 顺便说一句,您发布的问题启发了我扩展我的域验证代码以包含 URL 验证。我将在未来的版本中对此进行研究。
  • 在我的 URL 类中包含实际验证实际上是一件很棒的事情。感谢您的演练:)
【解决方案2】:

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

^(?#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})*)?$

【讨论】:

  • 我会试一试的。 (我只是试图粘贴我在这里使用的一个巨大的电子邮件正则表达式,但它比分配的 600 个字符大:S)
  • 请注意,在处理自定义 TLD 时,正则表达式可能很危险。
  • poke 的意思是,如果您使用的 tld 未在正则表达式中列入白名单,则会导致 url 失败。因此,如果您忘记允许 .tv 域名,则所有 .tv 域名都将被禁止。仅当您实际使用 TLD 白名单时,这才是正确的(此正则表达式似乎确实如此,但它也允许任何 2 char TLD)
  • 啊好吧,那我可能会稍微修改一下。如果我只匹配 a-z\.而不是针对列表进行测试,然后我知道我会抓住一切。我对无效的 TLD 不太在意
  • 这不允许非顶级域,是吗?即:example.co.uk
【解决方案3】:
!(https?://)?([-_a-z0-9]+\.)*([-_a-z0-9]+)\.([a-z]{2,4})(/?)(.*)!i

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

【讨论】:

    【解决方案4】:

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

    您最好使用@987654321@ 解析网址,然后检查您所需的所有位是否按顺序排列。

    补充: 这是我的 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 中的一些基础知识,即设置方案并且主机名中有一个点。

    【讨论】:

    • 如上面的 cmets 中所述,“此函数不用于验证给定的 URL” - 这不是它的预期行为。正则表达式用于匹配/替换字符串中的模式并为此进行了优化,您的建议可能涉及很多逻辑。
    • @poke:这就是为什么你必须检查它是否返回你需要的位。读书不难吗?
    • 它可能不是用来验证 URL,但它比你在那里找到的 URL 验证正则表达式的一半要好。
    猜你喜欢
    • 2010-09-17
    • 2011-06-17
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2012-02-22
    • 2015-11-08
    • 2018-08-06
    相关资源
    最近更新 更多