是否可以不使用正则表达式?
例如,我想检查字符串是否为有效域:
domain-name
abcd
example
是有效的域名。这些当然是无效的:
domaia@name
ab$%cd
等等。所以基本上它应该以字母数字字符开头,然后可能会有更多的alnum字符加上连字符。它也必须以alnum字符结束。
如果不可能,你能建议我采用正则表达式吗?
编辑:
为什么这不起作用?我错误地使用了preg_match吗?
$domain = '@djkal';
$regexp = '/^[a-zA-Z0-9][a-zA-Z0-9\-\_]+[a-zA-Z0-9]$/';
if (false === preg_match($regexp, $domain)) {
throw new Exception('Domain invalid');
}
答案 0 :(得分:127)
<?php
function is_valid_domain_name($domain_name)
{
return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) //valid chars check
&& preg_match("/^.{1,253}$/", $domain_name) //overall length check
&& preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name) ); //length of each label
}
?>
测试用例:
is_valid_domain_name? [a] Y
is_valid_domain_name? [0] Y
is_valid_domain_name? [a.b] Y
is_valid_domain_name? [localhost] Y
is_valid_domain_name? [google.com] Y
is_valid_domain_name? [news.google.co.uk] Y
is_valid_domain_name? [xn--fsqu00a.xn--0zwm56d] Y
is_valid_domain_name? [goo gle.com] N
is_valid_domain_name? [google..com] N
is_valid_domain_name? [google.com ] N
is_valid_domain_name? [google-.com] N
is_valid_domain_name? [.google.com] N
is_valid_domain_name? [<script] N
is_valid_domain_name? [alert(] N
is_valid_domain_name? [.] N
is_valid_domain_name? [..] N
is_valid_domain_name? [ ] N
is_valid_domain_name? [-] N
is_valid_domain_name? [] N
答案 1 :(得分:55)
通过这种方式,您不仅可以检查域是否具有有效格式,还可以检查域是否处于活动状态/是否已为其分配IP地址。
$domain = "stackoverflow.com";
if(filter_var(gethostbyname($domain), FILTER_VALIDATE_IP))
{
return TRUE;
}
请注意,此方法要求DNS条目处于活动状态,因此如果您需要在不使用DNS的情况下验证域字符串,请使用上面的velcrow提供的正则表达式方法。
此功能也不用于验证URL字符串使用FILTER_VALIDATE_URL。我们不对域使用FILTER_VALIDATE_URL,因为域字符串不是有效的URL。
答案 2 :(得分:8)
使用 checkdnsrr http://php.net/manual/en/function.checkdnsrr.php
$domain = "stackoverflow.com";
checkdnsrr($domain , "A");
//returns true if has a dns A record, false otherwise
答案 3 :(得分:7)
首先,你应该澄清你的意思是:
区分必要的原因是标签在技术上可以包含任何字符,包括NUL,@
和“.
”字符。 DNS具有8位功能,并且完全可以使用包含条目“ an\0odd\.l@bel
”的区域文件。当然不建议这样做,尤其是因为人们很难在标签内部分别标记那些分隔标签,但 是合法的。
但是, URL 中需要主机名称,并且这些名称由RFC 952和1123管理。有效的主机名称是子集域名称。特别是只允许使用字母,数字和连字符。此外,第一个和最后一个字符不能是连字符。 RFC 952不允许第一个字符的数字,但RFC 1123随后放宽了。
因此:
a
- 有效0
- 有效a-
- 无效a-b
- 有效xn--dasdkhfsd
- 有效(IDN的punycode编码)我不认为用一个简单的正则表达式使a-
示例失效是不可能的。我能想出的最好的单 主机标签是:
if (preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $label) &&
!preg_match('/-$/', $label))
{
# label is legal within a hostname
}
为了使问题更加复杂,一些域名条目(通常是SRV
条记录)使用带有下划线的标签,例如: _sip._udp.example.com
。这些是不是主机名,但它们是合法的域名。
答案 4 :(得分:6)
我认为,一旦你使用Erklan的想法隔离了域名:
$myUrl = "http://www.domain.com/link.php"; $myParsedURL = parse_url($myUrl); $myDomainName= $myParsedURL['host'];
你可以使用:
if( false === filter_var( $myDomainName, FILTER_VALIDATE_URL ) ) { // failed test }
PHP5s过滤功能只是出于我想象的目的。
我没有严格回答你的问题,因为它没有使用正则表达式,我意识到。
答案 5 :(得分:6)
PHP 7
// Validate a domain name
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN));
# string(33) "mandrill._domainkey.mailchimp.com"
// Validate an hostname (here, the underscore is invalid)
var_dump(filter_var('mandrill._domainkey.mailchimp.com', FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME));
# bool(false)
此处未记录:http://www.php.net/filter.filters.validate
,此处的错误请求位于此处:https://bugs.php.net/bug.php?id=72013
答案 6 :(得分:4)
这是没有正则表达式的另一种方式。
$myUrl = "http://www.domain.com/link.php";
$myParsedURL = parse_url($myUrl);
$myDomainName= $myParsedURL['host'];
$ipAddress = gethostbyname($myDomainName);
if($ipAddress == $myDomainName)
{
echo "There is no url";
}
else
{
echo "url found";
}
答案 7 :(得分:3)
正则表达式是检查域验证的最有效方法。如果您没有使用正则表达式(IMO是愚蠢的),那么您可以拆分域的每个部分:
然后,您必须检查某种循环中的每个字符,看它是否与有效域匹配。
就像我说的那样,使用正则表达式会更有效。
答案 8 :(得分:2)
您的正则表达式没问题,但您没有使用preg_match
。它返回int
(0或1),而不是布尔值。只需写下if(!preg_match($regex, $string)) { ... }
答案 9 :(得分:1)
如果您不想使用正则表达式,可以试试这个:
$str = 'domain-name';
if (ctype_alnum(str_replace('-', '', $str)) && $str[0] != '-' && $str[strlen($str) - 1] != '-') {
echo "Valid domain\n";
} else {
echo "Invalid domain\n";
}
但正如所说的regexp是最好的工具。
答案 10 :(得分:1)
正确的答案是你没有...你让一个经过单元测试的工具为你做的工作:
// return '' if host invalid --
private function setHostname($host = '')
{
$ret = (!empty($host)) ? $host : '';
if(filter_var('http://'.$ret.'/', FILTER_VALIDATE_URL) === false) {
$ret = '';
}
return $ret;
}
答案 11 :(得分:1)
一个有效的域名对我来说是我能够注册的东西,或者至少是我可以注册它的东西。这就是为什么我喜欢将它与“localhost”-names分开的原因。
最后我对主要问题感兴趣,如果避免Regex会更快,这是我的结果:
<?php
function filter_hostname($name, $domain_only=false) {
// entire hostname has a maximum of 253 ASCII characters
if (!($len = strlen($name)) || $len > 253
// .example.org and localhost- are not allowed
|| $name[0] == '.' || $name[0] == '-' || $name[ $len - 1 ] == '.' || $name[ $len - 1 ] == '-'
// a.de is the shortest possible domain name and needs one dot
|| ($domain_only && ($len < 4 || strpos($name, '.') === false))
// several combinations are not allowed
|| strpos($name, '..') !== false
|| strpos($name, '.-') !== false
|| strpos($name, '-.') !== false
// only letters, numbers, dot and hypen are allowed
/*
// a little bit slower
|| !ctype_alnum(str_replace(array('-', '.'), '', $name))
*/
|| preg_match('/[^a-z\d.-]/i', $name)
) {
return false;
}
// each label may contain up to 63 characters
$offset = 0;
while (($pos = strpos($name, '.', $offset)) !== false) {
if ($pos - $offset > 63) {
return false;
}
$offset = $pos + 1;
}
return $name;
}
?>
基准测试结果与velcrow 's function和10000次迭代相比较(complete results包含许多代码变体。找到最快的结果非常有趣。):
filter_hostname($domain);// $domains: 0.43556308746338 $real_world: 0.33749794960022
is_valid_domain_name($domain);// $domains: 0.81832790374756 $real_world: 0.32248711585999
$real_world
未包含极长的域名以产生更好的结果。现在我可以回答你的问题:使用ctype_alnum()
可以在没有正则表达式的情况下实现它,但由于preg_match()
更快,我更愿意这样做。
如果您不喜欢“local.host”是有效域名的事实,请使用this function代替公共tld列表。也许有人找到时间将两者结合起来。
答案 12 :(得分:1)
如果您想检查特定域名或IP地址是否存在,您也可以使用checkdnsrr
这是文档http://php.net/manual/en/function.checkdnsrr.php
答案 13 :(得分:0)
我知道这是一个老问题,但这是Google搜索的第一个答案,所以它似乎很有用。我最近遇到了同样的问题。我的解决方案就是使用公共后缀列表:
https://publicsuffix.org/learn/
列出的建议的语言特定库应该不仅可以轻松验证域格式,还可以验证顶级域名的有效性。
答案 14 :(得分:0)
如果可以运行Shell命令,则以下是确定域是否已注册的最佳方法。
如果未注册域名,此函数返回false,否则返回域名。
function get_domain_name($domain) {
//Step 1 - Return false if any shell sensitive chars or space/tab were found
if(escapeshellcmd($domain)!=$domain || count(explode(".", $domain))<2 || preg_match("/[\s\t]/", $domain)) {
return false;
}
//Step 2 - Get the root domain in-case of subdomain
$domain = (count(explode(".", $domain))>2 ? strtolower(explode(".", $domain)[count(explode(".", $domain))-2].".".explode(".", $domain)[count(explode(".", $domain))-1]) : strtolower($domain));
//Step 3 - Run shell command 'dig' to get SOA servers for the domain extension
$ns = shell_exec(escapeshellcmd("dig +short SOA ".escapeshellarg(explode(".", $domain)[count(explode(".", $domain))-1])));
//Step 4 - Return false if invalid extension (returns NULL), or take the first server address out of output
if($ns===NULL) {
return false;
}
$ns = (((preg_split('/\s+/', $ns)[0])[strlen(preg_split('/\s+/', $ns)[0])-1]==".") ? substr(preg_split('/\s+/', $ns)[0], 0, strlen(preg_split('/\s+/', $ns)[0])-1) : preg_split('/\s+/', $ns)[0]);
//Step 5 - Run another dig using the obtained address for our domain, and return false if returned NULL else return the domain name. This assumes an authoritative NS is assigned when a domain is registered, can be improved to filter more accurately.
$ans = shell_exec(escapeshellcmd("dig +noall +authority ".escapeshellarg("@".$ns)." ".escapeshellarg($domain)));
return (($ans===NULL) ? false : ((strpos($ans, $ns)>-1) ? false : $domain));
}
优点
缺点
答案 15 :(得分:0)
<?php
if(is_valid_domain('https://www.google.com')==1){
echo 'Valid';
}else{
echo 'InValid';
}
function is_valid_domain($url){
$validation = FALSE;
/*Parse URL*/
$urlparts = parse_url(filter_var($url, FILTER_SANITIZE_URL));
/*Check host exist else path assign to host*/
if(!isset($urlparts['host'])){
$urlparts['host'] = $urlparts['path'];
}
if($urlparts['host']!=''){
/*Add scheme if not found*/ if (!isset($urlparts['scheme'])){
$urlparts['scheme'] = 'http';
}
/*Validation*/
if(checkdnsrr($urlparts['host'], 'A') && in_array($urlparts['scheme'],array('http','https')) && ip2long($urlparts['host']) === FALSE){
$urlparts['host'] = preg_replace('/^www\./', '', $urlparts['host']);
$url = $urlparts['scheme'].'://'.$urlparts['host']. "/";
if (filter_var($url, FILTER_VALIDATE_URL) !== false && @get_headers($url)) {
$validation = TRUE;
}
}
}
return $validation;
}
?>
答案 16 :(得分:0)
在阅读了所有与添加功能有关的问题后,我决定我需要一些更准确的信息。 这就是我想出的对我有用的东西。
如果您需要专门验证主机名(它们必须以字母数字字符开头和结尾,并且仅包含字母数字和连字符),则此功能就足够了。
function is_valid_domain($domain) {
// Check for starting and ending hyphen(s)
if(preg_match('/-./', $domain) || substr($domain, 1) == '-') {
return false;
}
// Detect and convert international UTF-8 domain names to IDNA ASCII form
if(mb_detect_encoding($domain) != "ASCII") {
$idn_dom = idn_to_ascii($domain);
} else {
$idn_dom = $domain;
}
// Validate
if(filter_var($idn_dom, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) != false) {
return true;
}
return false;
}
请注意,此功能适用于大多数(尚未测试所有语言)LTR语言。不适用于RTL语言。
is_valid_domain('a'); Y
is_valid_domain('a.b'); Y
is_valid_domain('localhost'); Y
is_valid_domain('google.com'); Y
is_valid_domain('news.google.co.uk'); Y
is_valid_domain('xn--fsqu00a.xn--0zwm56d'); Y
is_valid_domain('area51.com'); Y
is_valid_domain('japanese.コム'); Y
is_valid_domain('домейн.бг'); Y
is_valid_domain('goo gle.com'); N
is_valid_domain('google..com'); N
is_valid_domain('google-.com'); N
is_valid_domain('.google.com'); N
is_valid_domain('<script'); N
is_valid_domain('alert('); N
is_valid_domain('.'); N
is_valid_domain('..'); N
is_valid_domain(' '); N
is_valid_domain('-'); N
is_valid_domain(''); N
is_valid_domain('-günter-.de'); N
is_valid_domain('-günter.de'); N
is_valid_domain('günter-.de'); N
is_valid_domain('sadyasgduysgduysdgyuasdgusydgsyudgsuydgusydgsyudgsuydusdsdsdsaad.com'); N
is_valid_domain('2001:db8::7'); N
is_valid_domain('876-555-4321'); N
is_valid_domain('1-876-555-4321'); N
答案 17 :(得分:-3)
这是javascript中域名的验证:
<script>
function frmValidate() {
var val=document.frmDomin.name.value;
if (/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/.test(val)){
alert("Valid Domain Name");
return true;
} else {
alert("Enter Valid Domain Name");
val.name.focus();
return false;
}
}
</script>
答案 18 :(得分:-3)
检查php函数checkdnsrr
function validate_email($email){
$exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";
if(eregi($exp,$email)){
if(checkdnsrr(array_pop(explode("@",$email)),"MX")){
return true;
}else{
return false;
}
}else{
return false;
}
}
答案 19 :(得分:-6)
这很简单。一些php引擎有split()的问题。 以下代码可以使用。
<?php
$email = "vladimiroliva@ymail.com";
$domain = strtok($email, "@");
$domain = strtok("@");
if (@getmxrr($domain,$mxrecords))
echo "This ". $domain." EXIST!";
else
echo "This ". $domain." does not exist!";
?>