我希望有一种方法可以验证域名而不是完整的URL,以下示例是我要寻找的:
example.com -> true
example.net -> true
example.org -> true
example.biz -> true
example.co.uk -> true
sub.example.com -> true
example.com/folder -> false
exam*$ple.com -> false
我希望有一种方法可以验证域名而不是完整的URL,以下示例是我要寻找的:
example.com -> true
example.net -> true
example.org -> true
example.biz -> true
example.co.uk -> true
sub.example.com -> true
example.com/folder -> false
exam*$ple.com -> false
被接受的答案是不完整/错误的。
正则表达式模式;
不应该验证诸如以下域名:
-example.com
, example--.com
, -example-.-.com
, example.000
等...
应该验证诸如以下域名:
schools.k12
, newTLD.clothing
, good.photography
等...
经过进一步研究,以下是我能想到的最正确、跨语言和紧凑的模式:
^(?!\-)(?:(?:[a-zA-Z\d][a-zA-Z\d\-]{0,61})?[a-zA-Z\d]\.){1,126}(?!\d+)[a-zA-Z\d]{1,63}$
注1:完整域名长度检查不包括在正则表达式中。应该通过本地方法进行简单检查,例如strlen(domain) <= 253
。
注2:此模式适用于大多数语言,包括PHP、Javascript、Python等...
请参见此处的演示(适用于JS、PHP、Python)
上述正则表达式不支持IDN。
没有规范说明扩展名(TLD)应该在2到6个字符之间。实际上支持63个字符。请参见当前的TLD列表 here。此外,一些网络内部使用自定义/伪造的TLD。
注册机构可能会强制实施一些额外的特定规则,这些规则在此正则表达式中没有明确支持。例如,.CO.UK
和.ORG.UK
必须至少有3个字符,但不能超过23个字符,不包括扩展名。这些规则是非标准的,可能会发生变化。如果无法维护,请勿实施这些规则。
正则表达式很棒,但并不是解决每个问题的最有效、最高效的方法。因此,应尽可能使用本地URL解析器。例如,Python的urlparse()
方法或PHP的parse_url()
方法...
毕竟,这只是格式验证。正则表达式测试并不能确认域名是否实际配置/存在!您应该通过发出请求来测试其存在性。
更新(2019-12-21):修复了子域名的前导连字符。
如何尝试:
^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$
/^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/
,它才能正常工作。例如,它可以与preg_match
函数一起使用,否则无法正常工作。 - Villapalos^(http[s]?\:\/\/)?((\w+)\.)?(([\w-]+)?)(\.[\w-]+){1,2}$
http/s://
www
-
和_
)-
和_
)http://www.test.example
test.com.mt
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.example","http://www.domain.example/folder" ,"http://domain.example", "www.domain.example", "domain.example/subfolder", "domain.example","sub.domain.example");
foreach ($domain as $v) {
echo isValidDomainName($v) ? "{$v} is valid<br>" : "{$v} is invalid<br>";
}
<?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" 布尔(false)我希望我已经涵盖了所有内容,如果我漏掉了什么,请告诉我,我可以改进这个函数。:)
之前我曾尝试寻找解决方案,但考虑到子域名的可能值,我可能错误地认为唯一确定某个内容是否有效的方法是检查这个数组(可以像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;
}
但也许我错了。你怎么看?
附言:我没有重新检查函数的逻辑,也许它可以缩短并且肯定可以改进。
$w3all_domains数组来自文件包含,其中存储了ICANN域-这是检查域是否有效并完成任何答案的唯一方法:或者我认为任何上面或下面的解决方案都有时不完整。
[编辑]
记住,正则表达式只能检查某些东西是否格式正确。www.idonotexistbecauseiammadeuponthespot.example
是格式正确的,但实际上并不存在...在写作时。;) 此外,某些免费的Web托管提供商(如Tripod)允许子域中使用下划线。这显然违反了RFC,但有时确实有效。
您想检查域名是否存在吗?请尝试使用dns_get_record而不是(仅仅)正则表达式。