【问题标题】:How to validate a domain name using Regex & Php?如何使用 Regex & Php 验证域名?
【发布时间】:2011-03-02 21:38:09
【问题描述】:

我想要一个仅验证域名而不是完整网址的解决方案,以下示例是我正在寻找的:

domain.com -> true
domain.net -> true
domain.org -> true
domain.biz -> true
domain.co.uk -> true
sub.domain.com -> true
domain.com/folder -> false
domµ*$ain.com -> false

【问题讨论】:

标签: php regex preg-match


【解决方案1】:

前段时间我结束了是否能够找到解决方案,但检查所有可能性,并且由于子域可能的值,我可能错误地相信(也许)知道某事是否存在的唯一方法是否有效,要检查这个数组(可以在 icann 网站的示例中提取)

http://www.axew3.com/www/data-hints/w3-all-top-level-domains-names-array.php

类似这样的:

// this extract ever the correct cookie domain (except for sub hosted/domains like: mydomain.my-hostingService-domain.com)

function extract_cookie_domain( $w3cookie_domain ) {

require_once( WPW3ALL_PLUGIN_DIR . 'addons/w3_icann_domains.php' );

$count_dot = substr_count($w3cookie_domain, ".");

     if($count_dot >= 3){
      preg_match('/.*(\.)([-a-z0-9]+)(\.[-a-z0-9]+)(\.[a-z]+)/', $w3cookie_domain, $w3m0, PREG_OFFSET_CAPTURE);
      $w3cookie_domain = $w3m0[2][0].$w3m0[3][0].$w3m0[4][0];
   }
   
   $ckcd = explode('.',$w3cookie_domain);
// $w3all_domains array come from file inclusion where icann domains are stored- This is the unique way to check if a domain is valid and to complete any answer, or any answer, will be incomplete
  if(!in_array('.'.$ckcd[1], $w3all_domains)){
   $w3cookie_domain = preg_replace('/^[^\.]*\.([^\.]*)\.(.*)$/', '\1.\2', $w3cookie_domain);
  }

    $w3cookie_domain = '.' . $w3cookie_domain;

$pos = strpos($w3cookie_domain, '.');
if($pos != 0){
    $w3cookie_domain = '.' . $w3cookie_domain;
}

return $w3cookie_domain;

}

但也许我错了。你说什么?

p.s 我没有重新检查函数的逻辑,可以缩短它并一定改进

$w3all_domains 数组来自存储 icann 域的文件包含 - 这是检查域是否有效并完成任何答案的唯一方法:或者我认为上面或下面的任何解决方案有时都会不完整。

[编辑]

【讨论】:

  • 这个问题要求“验证”,但您的回答似乎是在展示“提取”过程。你在回答所提出的问题吗?
  • 嗯,这是获得正确结果的独特方式,否则您将永远无法确定,如果您以前不会通过这样的事情。不是吗?
【解决方案2】:

接受的答案不完整/错误。

正则表达式模式;

  • 不应验证域,例如:
    -domain.comdomain--.com-domain-.-.comdomain.000 等...

  • 应该验证域,例如:
    schools.k12newTLD.clothinggood.photography 等...

经过进一步研究;以下是我能想到的最正确、跨语言和紧凑的模式:

^(?!\-)(?:(?:[a-zA-Z\d][a-zA-Z\d\-]{0,61})?[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$

此模式符合规范中定义的大多数*规则:

  • 每个标签/级别(由点分隔)最多可包含 63 个字符
  • 完整的域名最多可以有127级
  • 完整域名的文本长度不得超过 253 个字符
  • 每个标签可以由字母、数字和连字符组成。
  • 标签不能以连字符开始结束
  • 顶级域(扩展名)不能是全数字

注意 1:全域长度检查不包含在正则表达式中。它应该通过本机方法简单地检查,例如strlen(domain) <= 253.
注意 2:此模式适用于大多数语言,包括 PHP、Javascript、Python 等...

参见DEMO here(适用于 JS、PHP、Python)

更多信息:

  • 上面的正则表达式不支持IDNs。

  • 没有规定扩展名 (TLD) 应介于 2 到 6 个字符之间。它实际上支持 63 个字符。查看当前的TLD list here。此外,一些网络确实在内部使用自定义/伪 TLD。

  • 注册机构可能会施加一些额外的,specific rules,此正则表达式未明确支持。例如,.CO.UK.ORG.UK 必须至少有 3 个字符,但少于 23 个,不包括扩展名。这些类型的规则是非标准的,可能会发生变化。如果您无法维护,请不要实施它们。

  • 正则表达式很棒,但不是解决所有问题的最有效、最高效的解决方案。因此,应尽可能使用本机 URL 解析器。例如Python的urlparse()方法或者PHP的parse_url()方法...

  • 毕竟,这只是一个格式验证。正则表达式测试不能确认域名实际配置/存在!您应该通过发出请求来测试存在。

规格和参考:

更新 (2019-12-21):修复了带有子域的前导连字符。

【讨论】:

  • 次要附录,但鉴于 gTLD 是虚荣的,最好只强制执行 63 个字符的最大可能长度(请参阅stackoverflow.com/questions/9238640/…)。
  • 但是不验证test--0.com,无效。
  • 这是一个有效的域,上面的正则表达式将其验证为一个域。在此处查看演示:regex101.com/r/fC7zU9/1
  • 不匹配这个:go.xn--fiqs8s
  • @MarinosAn 这是一个国际域名后缀。该帖子清楚地表明正则表达式不支持 IDN。
【解决方案3】:

我做了一个函数来验证没有任何正则表达式的域名。

<?php
function validDomain($domain) {
  $domain = rtrim($domain, '.');
  if (!mb_stripos($domain, '.')) {
    return false;
  }
  $domain = explode('.', $domain);
  $allowedChars = array('-');
  $extenion = array_pop($domain);
  foreach ($domain as $value) {
    $fc = mb_substr($value, 0, 1);
    $lc = mb_substr($value, -1);
    if (
      hash_equals($value, '')
      || in_array($fc, $allowedChars)
      || in_array($lc, $allowedChars)
    ) {
      return false;
    }
    if (!ctype_alnum(str_replace($allowedChars, '', $value))) {
      return false;
    }
  }
  if (
    !ctype_alnum(str_replace($allowedChars, '', $extenion))
    || hash_equals($extenion, '')
  ) {
    return false;
  }
  return true;
}
$testCases = array(
  'a',
  '0',
  'a.b',
  'google.com',
  'news.google.co.uk',
  'xn--fsqu00a.xn--0zwm56d',
  'google.com ',
  'google.com.',
  'goo gle.com',
  'a.',
  'hey.hey',
  'google-.com',
  '-nj--9*.vom',
  ' ',
  '..',
  'google..com',
  'www.google.com',
  'www.google.com/some/path/to/dir/'
);
foreach ($testCases as $testCase) {
  var_dump($testCase);
  var_dump(validDomain($TestCase));
  echo '<br /><br />';
}
?>

此代码输出:

字符串(1)“a”布尔(假)

字符串(1)“0”布尔(假)

字符串(3)“a.b”布尔(真)

字符串(10)“google.com”布尔(真)

字符串(17)“news.google.co.uk”布尔(真)

字符串(23)“xn--fsqu00a.xn--0zwm56d”布尔(真)

字符串(11)“google.com”布尔(假)

字符串(11)“google.com。”布尔(真)

字符串(11)“goo gle.com”布尔(假)

字符串(2)“一个。”布尔(假)

字符串(7)“嘿。嘿”布尔(真)

字符串(11)“google-.com”布尔(假)

字符串(11)“-nj--9*.vom”布尔(假)

字符串(1)“”布尔(假)

字符串(2)“..”布尔(假)

字符串(11)“google..com”布尔(假)

string(14) "www.google.com" bool(true)

字符串(32)“www.google.com/some/path/to/dir/”布尔(假)

如果我遗漏了什么,我希望我已经涵盖了所有内容,请告诉我,我可以改进此功能。 :)

【讨论】:

    【解决方案4】:

    在我的例子中,如果格式是 stackoverflow.com 或 xxx.stackoverflow.com,则域名被认为是有效的

    因此,除了其他堆栈答案之外,我还添加了对 www 的检查。还。

    function isValidDomainName($domain) {
      if (filter_var(gethostbyname($domain), FILTER_VALIDATE_IP)) {
          return (preg_match('/^www./', $domain)) ? FALSE : TRUE;
      }
      return FALSE;
    }
    

    你可以用这段代码测试函数

        $domain = array("http://www.domain.com","http://www.domain.com/folder" ,"http://domain.com", "www.domain.com", "domain.com/subfolder", "domain.com","sub.domain.com");
        foreach ($domain as $v) {
            echo isValidDomainName($v) ? "{$v} is valid<br>" : "{$v} is invalid<br>";
        }
    

    【讨论】:

      【解决方案5】:

      请试试这个表达方式:

      ^(http[s]?\:\/\/)?((\w+)\.)?(([\w-]+)?)(\.[\w-]+){1,2}$
      

      它实际上做了什么

      • 可选http/s://
      • 可选 www
      • 任何有效的字母数字名称(包括 - 和 _)
      • 任何有效的字母数字名称出现 1 或 2 次(包括 - 和 _)

      验证示例

      【讨论】:

      • 这个例子很完美,涵盖了 http(s)://www.abc.com www.abc.com abc.com subdomain.abc.com
      【解决方案6】:

      请记住,正则表达式只能检查某些内容是否格式正确。 “www.idonotexistbecauseiammadeuponthespot.com”格式正确,但实际上并不存在……在撰写本文时。 ;) 此外,某些免费网络托管服务提供商(如 Tripod)允许在子域中使用下划线。这显然违反了 RFC,但它有时会起作用。

      您要检查域是否存在?尝试dns_get_record 而不是(仅)一个正则表达式。

      【讨论】:

        【解决方案7】:

        怎么样:

        ^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$
        

        【讨论】:

        • 为什么投反对票?我在regexpal.com 对其进行了测试,它匹配了所有 OP 的测试数据。
        • 投反对票的人将其收回。 @Lauri .museum.travel
        • @zildjohn01 今天也学到了一些新东西 ;-) 谢谢
        • 这个答案是(不是完全错误的)但是不完整。请参阅我的答案中的更正。
        • 如果你把 REGEX 写成这样,它只在 PHP 中有效:/^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/。例如,它适用于 preg_match 函数,否则不适用。
        猜你喜欢
        • 2023-04-01
        • 2010-12-17
        • 2013-08-22
        • 2011-03-08
        • 2012-05-30
        • 1970-01-01
        • 2016-01-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多